synapsecns/sanguine

View on GitHub
agents/contracts/test/destinationharness/destinationharness.contractinfo.json

Summary

Maintainability
Test Coverage
{"solidity/DestinationHarness.t.sol:Address":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207869384d1b8348e94465e7831e06f9839d895c935397e6a0cbb84cbfa5863fc464736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207869384d1b8348e94465e7831e06f9839d895c935397e6a0cbb84cbfa5863fc464736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"44358:9169:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;44358:9169:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"44358:9169: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/DestinationHarness.t.sol\":\"Address\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:AddressUpgradeable":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220074555f9e88c974632499377298db08586245e86b69fefc1e20adf60d4c9b3d664736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220074555f9e88c974632499377298db08586245e86b69fefc1e20adf60d4c9b3d664736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"88838:9180:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;88838:9180:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"88838: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/DestinationHarness.t.sol\":\"AddressUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"AgentSecured\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"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/DestinationHarness.t.sol:AttestationLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212208d8842eee705e0b318530934a6a4bf023ad014eb6fca63ee4a6070d316a0bd7c64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212208d8842eee705e0b318530934a6a4bf023ad014eb6fca63ee4a6070d316a0bd7c64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"198769:5436:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;198769:5436:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"198769:5436:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"# Attestation Attestation structure represents the \"Snapshot Merkle Tree\" created from every Notary snapshot accepted by the Summit contract. Attestation includes\" the root of the \"Snapshot Merkle Tree\", as well as additional metadata. ## Steps for creation of \"Snapshot Merkle Tree\": 1. The list of hashes is composed for states in the Notary snapshot. 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT. 3. Values from the list are used as leafs and the merkle tree is constructed. ## Differences between a State and Attestation Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract. The main difference is that Origin contract itself is keeping track of an incremental merkle tree, by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\". While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the \"Snapshot Merkle Root\". - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\". - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the time snapshot was submitted\" + \"attestation metadata\". ## Attestation validity - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce) snapshot submitted by Notaries, as well as the historical agent merkle root. - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\". - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying snapshot is invalid (i.e. one of the states in the list is invalid). - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect). - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts. # Memory layout of Attestation fields | Position   | Field       | Type    | Bytes | Description                                                    | | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- | | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot | | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         | | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  | | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         | | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |","version":1},"developerDoc":{"details":"Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving messages coming from origin chains that the initial snapshot refers to.","kind":"dev","methods":{},"stateVariables":{"OFFSET_SNAP_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\":\"Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving messages coming from origin chains that the initial snapshot refers to.\",\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"OFFSET_SNAP_ROOT\":{\"details\":\"The variables below are not supposed to be used outside of the library directly.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"# Attestation Attestation structure represents the \\\"Snapshot Merkle Tree\\\" created from every Notary snapshot accepted by the Summit contract. Attestation includes\\\" the root of the \\\"Snapshot Merkle Tree\\\", as well as additional metadata. ## Steps for creation of \\\"Snapshot Merkle Tree\\\": 1. The list of hashes is composed for states in the Notary snapshot. 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT. 3. Values from the list are used as leafs and the merkle tree is constructed. ## Differences between a State and Attestation Similar to Origin, every derived Notary's \\\"Snapshot Merkle Root\\\" is saved in Summit contract. The main difference is that Origin contract itself is keeping track of an incremental merkle tree, by inserting the hash of the sent message and calculating the new \\\"Origin Merkle Root\\\". While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the \\\"Snapshot Merkle Root\\\". - Origin's State is \\\"state of Origin Merkle Tree after N-th message was sent\\\". - Summit's Attestation is \\\"data for the N-th accepted Notary Snapshot\\\" + \\\"agent merkle root at the time snapshot was submitted\\\" + \\\"attestation metadata\\\". ## Attestation validity - Attestation is considered \\\"valid\\\" in Summit contract, if it matches the N-th (nonce) snapshot submitted by Notaries, as well as the historical agent merkle root. - Attestation is considered \\\"valid\\\" in Origin contract, if its underlying Snapshot is \\\"valid\\\". - This means that a snapshot could be \\\"valid\\\" in Summit contract and \\\"invalid\\\" in Origin, if the underlying snapshot is invalid (i.e. one of the states in the list is invalid). - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect). - Attestation is considered \\\"globally valid\\\", if it is valid in the Summit and all the Origin contracts. # Memory layout of Attestation fields | Position   | Field       | Type    | Bytes | Description                                                    | | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- | | [000..032) | snapRoot    | bytes32 | 32    | Root for \\\"Snapshot Merkle Tree\\\" created from a Notary snapshot | | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         | | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  | | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         | | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"AttestationLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:BaseMessageLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122012440a8d6cbe4d7c10d5271d6b0ef50ccd5af2f3b0ab96878a44472951f698e364736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122012440a8d6cbe4d7c10d5271d6b0ef50ccd5af2f3b0ab96878a44472951f698e364736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"237878:4880:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;237878:4880:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"237878: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/DestinationHarness.t.sol\":\"BaseMessageLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:ByteString":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209b6c5507b7e61d0fe84cb948f32424de54836f5223e678dcf53a2ec0c05b646064736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209b6c5507b7e61d0fe84cb948f32424de54836f5223e678dcf53a2ec0c05b646064736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"181236:9194:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;181236:9194:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"181236: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/DestinationHarness.t.sol\":\"ByteString\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:ChainContext":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220157983c9060d3e1c4a729e37758c0dec5535c211a5ea41f96ff77bd547d5a14464736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220157983c9060d3e1c4a729e37758c0dec5535c211a5ea41f96ff77bd547d5a14464736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"101804:976:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;101804:976:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"101804: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/DestinationHarness.t.sol\":\"ChainContext\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"ContextUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:Destination":{"code":"0x6101406040523480156200001257600080fd5b50604051620053ac380380620053ac83398101604081905262000035916200015b565b60408051808201909152600580825264302e302e3360d81b60208301526080528383838383816200006681620001af565b60a081815250505062000083620000b360201b620020171760201c565b63ffffffff90811660c0521660e052506001600160a01b0391821661010052166101205250620001d79350505050565b6000620000cb46620000d060201b6200201e1760201c565b905090565b600063ffffffff8211156200013a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840160405180910390fd5b5090565b80516001600160a01b03811681146200015657600080fd5b919050565b6000806000606084860312156200017157600080fd5b835163ffffffff811681146200018657600080fd5b925062000196602085016200013e565b9150620001a6604085016200013e565b90509250925092565b80516020808301519190811015620001d1576000198160200360031b1b821691505b50919050565b60805160a05160c05160e05161010051610120516150ba620002f26000396000818161059e0152818161087801528181610935015261316001526000818161043d01528181610cda01528181610ed5015281816117ea0152818161190a01528181611ba201528181611d0d015281816120f3015281816121a90152613042015260008181610416015281816107f201528181610c7f0152818161176401528181611b470152818161269e01526130f50152600081816104970152818161081901528181610ca6015281816110b9015281816111310152818161178b01528181611b6e01528181612675015281816127940152818161311c015281816133ce01526134a20152600061039a0152600061037701526150ba6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80637622f78d11610104578063a554d1e3116100a2578063e2f006f711610071578063e2f006f714610562578063e30c397814610575578063f2fde38b14610586578063fb0e722b1461059957600080fd5b8063a554d1e3146104f0578063d0dd0675146104f8578063daa74a9e1461052f578063dfadd81a1461054257600080fd5b80638d3638f4116100de5780638d3638f4146104925780638da5cb5b146104b95780639498bd71146104ca578063a2155c34146104dd57600080fd5b80637622f78d1461043857806379ba509714610477578063883099bc1461047f57600080fd5b8063409891521161017c57806360fc84661161014b57806360fc8466146103d457806361169218146103f4578063715018a614610409578063717b86381461041157600080fd5b806340989152146102dc5780634f1275671461033c57806354fd4d501461036b57806355252dd1146103cc57600080fd5b8063305b29ee116101b8578063305b29ee1461024a57806339fe2736146102865780633c6cf473146102a95780633cf7b120146102c957600080fd5b806328f3fac9146101df57806329be4db2146102085780632de5aaf714610229575b600080fd5b6101f26101ed366004614676565b6105c0565b6040516101ff91906146f7565b60405180910390f35b61021b610216366004614705565b6105ec565b6040516101ff92919061476e565b61023c610237366004614705565b6108fa565b6040516101ff929190614793565b6102716102583660046147c2565b6101616020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101ff565b6102996102943660046148bd565b610928565b60405190151581526020016101ff565b6102bc6102b7366004614705565b610bcd565b6040516101ff91906149e2565b61012f545b6040519081526020016101ff565b610160546103129064ffffffffff80821691650100000000008104909116906a0100000000000000000000900463ffffffff1683565b6040805164ffffffffff948516815293909216602084015263ffffffff16908201526060016101ff565b61027161034a366004614705565b60009081526101306020526040902054640100000000900463ffffffff1690565b604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516101ff91906149f5565b6102ce610c7b565b6103e76103e2366004614a54565b610d5f565b6040516101ff9190614a96565b610407610402366004614b2a565b610eca565b005b610407610fe6565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ff565b610407610ff0565b61040761048d366004614b63565b611083565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b6033546001600160a01b031661045f565b6104076104d8366004614705565b611648565b6104076104eb366004614b2a565b6118ff565b610299611b43565b61050b6105063660046147c2565b611d7b565b604080516bffffffffffffffffffffffff90931683526020830191909152016101ff565b6103bf61053d366004614705565b611e48565b6105556105503660046147c2565b611ee7565b6040516101ff9190614c2c565b610299610570366004614c67565b611f7b565b6065546001600160a01b031661045f565b610407610594366004614676565b611f8e565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b60408051606081018252600080825260208201819052918101919091526105e68261209e565b92915050565b61012f546060908190831061062d576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061012f848154811061064357610643614c9c565b600091825260208083209091015480835261013082526040808420815160e081018352815463ffffffff8082168352640100000000820481169683019690965264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909516608082015276010000000000000000000000000000000000000000000090940490911660a08401526001015460c08301526101628054919450919291908790811061071c5761071c614c9c565b90600052602060002090600202016040518060400160405290816000820154815260200160018201548152505090506107ee8382602001518460200151856040015186606001516040805160208101969096528581019490945260e09290921b7fffffffff0000000000000000000000000000000000000000000000000000000016606085015260d890811b7fffffffffff000000000000000000000000000000000000000000000000000000908116606486015291901b1660698301528051604e818403018152606e909201905290565b94507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146108f25760c08201516040517fddeffa6600000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ddeffa6690602401600060405180830381865afa1580156108c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108ef9190810190614ccb565b93505b505050915091565b6040805160608101825260008082526020820181905291810182905261091f8361215e565b91509150915091565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461098c576040517fdbc2fa8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109958661221c565b156109cc576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109d586612251565b15610a0c576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a1785612328565b90506000610a248261233b565b63ffffffff808a166000908152610161602052604090205491925090811690821611610a7c576040517f7b7fd2c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88811660009081526101616020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016918316919091179055610acb82898961234d565b6101626040518060400160405280878152602001610ae8856125f0565b905281546001818101845560009384526020808520845160029094020192835590920151910155610b17611b43565b9050610b2481878b612601565b80516101608054602084015160409094015163ffffffff166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff64ffffffffff95861665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000090931695909416949094171791909116919091179055610bbc858a61274a565b600193505050505b95945050505050565b600081815261012d602090815260408083208151608081018352905463ffffffff80821683526401000000008204169382019390935268010000000000000000830460ff169181019190915269010000000000000000009091046001600160a01b03166060820181905215610c455750600292915050565b600083815261012e60205260409020546001600160a01b031615610c6c5750600192915050565b50600092915050565b50919050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1614610cd8575061015f5490565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5a9190614d39565b905090565b6060818067ffffffffffffffff811115610d7b57610d7b6147df565b604051908082528060200260200182016040528015610dc157816020015b604080518082019091526000815260606020820152815260200190600190039081610d995790505b5091503660005b82811015610ec157858582818110610de257610de2614c9c565b9050602002810190610df49190614d52565b91506000848281518110610e0a57610e0a614c9c565b60200260200101519050306001600160a01b0316838060200190610e2e9190614d90565b604051610e3c929190614df5565b600060405180830381855af49150503d8060008114610e77576040519150601f19603f3d011682016040523d82523d6000602084013e610e7c565b606091505b5060208301521515808252833517610eb8577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610dc8565b50505092915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f2c576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f36612967565b63ffffffff848116600090815260c960205260409020805464ffffffffff84166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff00909116176002179055909150821615610fe15763ffffffff8216600090815260c96020526040902080547fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff0016660100000000000064ffffffffff8416021790555b505050565b610fee612972565b565b60655433906001600160a01b031681146110775760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b611080816129cc565b50565b61108b6129fd565b600061109688612a56565b905060006110a382612a69565b905060006110b083612a7f565b905063ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602083901c6cffffffffffffffffffffffffff1663ffffffff161461112a576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016606083901c64ffffffffff1663ffffffff160361119a576040517f3eeb1dd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815261012d60209081526040918290208251608081018452905463ffffffff80821683526401000000008204169282019290925268010000000000000000820460ff1692810192909252690100000000000000000090046001600160a01b0316606082018190521561123b576040517f0dc1019700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061124c84848d8d8d8d8d612b3f565b905060008160a0015164ffffffffff16426112679190614e34565b905063ffffffff85168110156112a9576040517f5e5728e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080806112c98870ffffffffffffffffffffffffffffffffff16612db1565b60018111156112da576112da614693565b036113135760006112f26112ed8a612de4565b612df0565b905061130088858c84612e31565b915061130b81612fd1565b925050611329565b61132687846113218b612de4565b612fe2565b90505b845163ffffffff1660000361147e5763ffffffff606088901c81168652608085015116602086015260ff8a166040860152801561136b573360608601526113a3565b600086815261012e6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b600086815261012d602090815260409182902087518154928901519389015160608a01516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9092166801000000000000000002919091167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff968716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009096169690931695909517939093171692909217179055611597565b806114b5576040517f589a41b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360608601908152600087815261012d602090815260409182902088518154928a0151938a015194516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9096166801000000000000000002959095167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090951695909216949094179290921791909116919091179190911790555b6040518115158152869063ffffffff60608a901c16907f39c48fd1b2185b07007abc7904a8cdf782cfe449fd0e9bba1c2223a691e15f0b9060200160405180910390a36115ef846000015185602001518885896130f1565b61162d5760408051878152602081018490527f22bd0cccf7173839e6f30c797b419921d48a23b0732d0b120c600a49247d3016910160405180910390a15b505050505050505061163f600160fb55565b50505050505050565b600054610100900460ff16158080156116685750600054600160ff909116105b806116825750303b158015611682575060005460ff166001145b6116f45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161106e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561175257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61175a61320d565b611762613292565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146118985761015f8290556040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b15801561183657600080fd5b505af115801561184a573d6000803e3d6000fd5b50505050611856612967565b610160805464ffffffffff9290921665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff9092169190911790555b80156118fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611961576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061196b612967565b9050600060405180606001604052806001600281111561198d5761198d614693565b815264ffffffffff84166020808301919091526000604092830181905263ffffffff8816815260c99091522081518154929350839282907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156119fa576119fa614693565b0217905550602082810151825460409485015164ffffffffff9081166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff9190931661010002167fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff909116171790915563ffffffff8516600090815260c990915220815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115611ac457611ac4614693565b0217905550602082015181546040909301517fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff90931661010064ffffffffff928316027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff16176601000000000000919093160291909117905550505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1603611b9e5750600090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c229190614d39565b61015f54909150808203611c395760009250505090565b604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff1691810182905290611c859061221c565b15611c9657505061015f5550600090565b611ca38160400151612251565b15611cb2576001935050505090565b60208101514290611cc7906201518090614e47565b64ffffffffff161115611cde576001935050505090565b6040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b158015611d5957600080fd5b505af1158015611d6d573d6000803e3d6000fd5b505050506000935050505090565b63ffffffff818116600090815261016360209081526040808320815160608101835290546bffffffffffffffffffffffff811682526c0100000000000000000000000081049095169281019290925270010000000000000000000000000000000090930464ffffffffff16928101839052909182919015801590611e095750611e07816020015161221c565b155b8015611e1f5750611e1d8160200151612251565b155b15611e425780516040820151909350611e3f9064ffffffffff1642614e34565b91505b50915091565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b03166060808301919091529290919003611ed6575050604080516020810190915260008152919050565b611ee08382613317565b9392505050565b604080516060810182526000808252602082018190529181019190915263ffffffff8216600090815260c96020526040908190208151606081019092528054829060ff166002811115611f3c57611f3c614693565b6002811115611f4d57611f4d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015292915050565b60006105e6611f898361348b565b61349e565b611f96612972565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611fdf6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610d5a465b600063ffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f3220626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b5090565b60408051606081018252600080825260208201819052918101919091526040517f28f3fac90000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000016906328f3fac990602401606060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e69190614ee8565b604080516060810182526000808252602082018190529181018290526040517f2de5aaf7000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632de5aaf790602401608060405180830381865afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190614f04565b60008063ffffffff8316600090815260c9602052604090205460ff16600281111561224957612249614693565b141592915050565b63ffffffff8116600090815260c96020526040808220815160608101909252805483929190829060ff16600281111561228c5761228c614693565b600281111561229d5761229d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015290506000815160028111156122dc576122dc614693565b146122ea5750600092915050565b806020015164ffffffffff166000036123065750600092915050565b60408101516123189061a8c090614e47565b64ffffffffff1642109392505050565b60006105e661233683613749565b61375c565b60006105e660406004845b919061379d565b6000612358846137be565b60008181526101306020526040902054909150760100000000000000000000000000000000000000000000900464ffffffffff16156123c3576040517fa789712900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808463ffffffff1681526020016123e38661233b565b63ffffffff1681526020016123f7866137cc565b64ffffffffff16815260200161240c866137db565b64ffffffffff16815260200161242761012f8054905061201e565b63ffffffff16815260200161243a612967565b64ffffffffff90811682526020918201949094526000838152610130825260408082208451815494860151928601516060870151608088015160a08901518b16760100000000000000000000000000000000000000000000027fffffffffff0000000000ffffffffffffffffffffffffffffffffffffffffffff63ffffffff928316720100000000000000000000000000000000000002167fffffffffff000000000000000000ffffffffffffffffffffffffffffffffffff938d166d0100000000000000000000000000027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff95909d166801000000000000000002949094167fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff978316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909a16929095169190911797909717949094169190911797909717919091169590951791909117845560c09091015160019384015561012f8054938401815590527f232da9e50dad2971456a78fb5cd6ff6b75019984d6e918139ce990999420f979909101555050565b60006105e6602080845b91906137ea565b604080516060810182526000808252602082018190529181019190915250604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff169181019190915261266a612967565b64ffffffffff1681527f000000000000000000000000000000000000000000000000000000000000000063ffffffff9081167f000000000000000000000000000000000000000000000000000000000000000091909116148015906126cd575083155b80156126dc57508261015f5414155b15611ee0576126e9612967565b64ffffffffff16602082015263ffffffff821660408083019190915261015f849055517fc8ba82607c756c8ae67c7e47c27ade0b0718d492495044a1f8619663f26ebaa39061273b9085815260200190565b60405180910390a19392505050565b815160005b8181101561296157600084828151811061276b5761276b614c9c565b602002602001015190506000612790826fffffffffffffffffffffffffffffffff1690565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff16036127cc57505061294f565b63ffffffff81811660009081526101636020908152604091829020825160608101845290546bffffffffffffffffffffffff8082168084526c0100000000000000000000000083049096168385015270010000000000000000000000000000000090910464ffffffffff1693820193909352929085901c909116908103612856575050505061294f565b6040518060600160405280826bffffffffffffffffffffffff1681526020018863ffffffff168152602001612889612967565b64ffffffffff90811690915263ffffffff9485166000908152610163602090815260409182902084518154928601519590930151909316700100000000000000000000000000000000027fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff949097166c01000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009091166bffffffffffffffffffffffff909216919091171791909116939093179092555050505b8061295981614f3a565b91505061274f565b50505050565b6000610d5a426138f4565b6033546001600160a01b03163314610fee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161106e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561108081613971565b600260fb5403612a4f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161106e565b600260fb55565b60006105e6612a6483613749565b6139db565b60006105e6612a7a82601185612346565b613a1c565b600080612a8b83612a69565b90506000612aab8270ffffffffffffffffffffffffffffffffff16612db1565b6001811115612abc57612abc614693565b03612b0057611ee0612ae78270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612af66112ed87612de4565b613a60565b613a86565b611ee0612b268270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612b3a612b3587612de4565b613ad2565b613b13565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526000612bdc600160408b901c68ffffffffffffffffff16612b999190614f72565b63ffffffff168989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060209250613b23915050565b90506000612c2b8260608c901c64ffffffffff168888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250613bcb915050565b600081815261013060209081526040808320815160e081018352815463ffffffff8082168352640100000000820481169583019590955264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909416608082015276010000000000000000000000000000000000000000000090930490911660a0830181905260019091015460c083015290955091925003612d20576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d2b9061221c565b15612d62576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d6d90612251565b15612da4576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050979650505050505050565b6000612dd08270ffffffffffffffffffffffffffffffffff1660801c90565b60ff1660018111156105e6576105e6614693565b600081611ee081613c2b565b6000612dfb82613c42565b61209a576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080612e3d83613c77565b905067ffffffffffffffff602082901c81169085161015612e8a576040517fed43c3a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612e9b612e9885613c93565b90565b90508467ffffffffffffffff165a11612ee0576040517faa6c898500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000606088901c64ffffffffff16604089901c68ffffffffffffffffff16612f07876125f0565b8977ffffffffffffffffffffffffffffffffffffffffffffffff8716612f34612f2f8b613ca2565b613cc5565b604051602401612f4996959493929190614f8f565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f032f287e000000000000000000000000000000000000000000000000000000001790529050612fc36001600160a01b03831667ffffffffffffffff8816600084613d04565b93505050505b949350505050565b60006105e6612e9882602085612346565b600080612fee83613ad2565b90506000613031606087901c64ffffffffff166040805163ffffffff9092166020830152810187905260600160408051601f198184030181529190528390613d36565b905060006130686001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683613e64565b9050805160201415806130ad575061307f83613ea8565b7fffffffff00000000000000000000000000000000000000000000000000000000166130aa82614fcc565b14155b156130e4576040517ff8b4221800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff161461314e57506000610bc4565b8260000361315e57506000610bc4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636b47b3bc87878661319a8988613317565b6040518563ffffffff1660e01b81526004016131b9949392919061500e565b6020604051808303816000875af11580156131d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fc919061503d565b9695505050505050565b600160fb55565b600054610100900460ff1661328a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613eb7565b600054610100900460ff1661330f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613f3d565b600082815261012e60205260409020546060906001600160a01b03168061333f575060608201515b600061012f846020015163ffffffff168154811061335f5761335f614c9c565b6000918252602080832090910154808352610130909152604082205490925061338d9063ffffffff1661215e565b5085516040808801516060808a0151835160e095861b7fffffffff0000000000000000000000000000000000000000000000000000000090811660208301527f000000000000000000000000000000000000000000000000000000000000000090961b9095166024860152602885018c90526048850188905260f89290921b7fff0000000000000000000000000000000000000000000000000000000000000016606885015284811b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116606986015288821b8116607d86015291901b1660918301528051608581840301815260a590920190529091506131fc565b60006105e661349983613749565b613fba565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff166134d083613ffb565b63ffffffff161461350d576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061351883614009565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b031660608201529293509003613596575060009392505050565b805163ffffffff166135a785614018565b63ffffffff161415806135cc5750806040015160ff166135c685614026565b60ff1614155b156135db575060009392505050565b60006135e685614035565b60008181526101306020526040812054919250906136099063ffffffff1661215e565b50905061012f836020015163ffffffff168154811061362a5761362a614c9c565b90600052602060002001548214158061365d5750806001600160a01b031661365187614044565b6001600160a01b031614155b1561366e5750600095945050505050565b600084815261012e60205260409020546001600160a01b0316806136e15783606001516001600160a01b03166136a388614053565b6001600160a01b03161480156136d6575083606001516001600160a01b03166136cb88614060565b6001600160a01b0316145b979650505050505050565b60006136ec88614060565b9050816001600160a01b031661370189614053565b6001600160a01b031614801561373d57506001600160a01b038116158061373d575084606001516001600160a01b0316816001600160a01b0316145b98975050505050505050565b805160009060208301612fc9818361406d565b6000613767826140d0565b61209a576040517feb92662c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806137ab8585856137ea565b602084900360031b1c9150509392505050565b60006105e6816020846125fa565b60006105e66044600584612346565b60006105e66049600584612346565b6000816000036137fc57506000611ee0565b6020821115613837576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416613854838561505f565b111561388c576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b600061389d8660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b600064ffffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201527f3020626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006139e6826140ef565b61209a576040517fd082b2a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600160ff608084901c16111561209a576040517f58ebbfbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6613a7d613a7184612fd1565b60009081526020902090565b612afb846141a4565b600082158015613a94575081155b15613aa1575060006105e6565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506105e6565b6000613add826141b4565b61209a576040517f9d46362800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6826141f0565b6141f0565b815160009082811115613b62576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84915060005b81811015613b9f57613b9583868381518110613b8657613b86614c9c565b6020026020010151898461421b565b9250600101613b68565b50805b83811015613bc157613bb7836000898461421b565b9250600101613ba2565b5050949350505050565b60006101fe600183901b1660408110613c10576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613c1c8787614244565b90506136d68282876006613b23565b60006105e6613c3b60118361505f565b83906142a5565b60006018613c526020604061505f565b613c5c919061505f565b6fffffffffffffffffffffffffffffffff8316101592915050565b60006105e6612e98613c8b6020604061505f565b601885612346565b60006105e660406020846125fa565b60006105e66018613cb56020604061505f565b613c3b919061505f565b906142a5565b60405180613cd6836020830161430b565b506fffffffffffffffffffffffffffffffff83166000601f8201601f19168301602001604052509052919050565b6000846001600160a01b03163b600003613d2057506000612fc9565b600080835160208501868989f195945050505050565b6060613d448251601f161590565b613d7a576040517fd49e9d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160038082526080820190925260009160208201606080368337019050509050613dec613da985613ea8565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091166020820152602401604051602081830303815290604052613749565b81600081518110613dff57613dff614c9c565b602002602001018181525050613e1483613749565b81600181518110613e2757613e27614c9c565b602002602001018181525050613e3c846143b4565b81600281518110613e4f57613e4f614c9c565b602002602001018181525050612fc9816143c2565b6060611ee0838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250614400565b600081611ee0818360046137ea565b600054610100900460ff16613f345760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee336129cc565b600054610100900460ff166132065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b6000613fc5826144e7565b61209a576040517f76b4e13c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e660048084612346565b60006105e660086020846125fa565b60006105e681600484612346565b60006105e66048600184612346565b60006105e660286020846125fa565b60006105e66049835b90614503565b60006105e6605d8361404d565b60006105e660718361404d565b60008061407a838561505f565b905060405181111561408a575060005b806000036140c4576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317612fc9565b6000604e6fffffffffffffffffffffffffffffffff83165b1492915050565b60006fffffffffffffffffffffffffffffffff821661410f60118361505f565b81101561411f5750600092915050565b600061412a84614511565b9050600160ff608083901c161115614146575060009392505050565b600061416c61415483613a1c565b70ffffffffffffffffffffffffffffffffff16612db1565b600181111561417d5761417d614693565b0361419357612fc961418e85613c2b565b613c42565b612fc961419f85613c2b565b6141b4565b60006105e6613b1e602084613cbf565b60006fffffffffffffffffffffffffffffffff821660048110156141db5750600092915050565b611ee06141e9600483614e34565b601f161590565b6000806141fd8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b6000600183831c16810361423a576142338585613a86565b9050612fc9565b6142338486613a86565b6000828260405160200161428792919091825260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015260240190565b60405160208183030381529060405280519060200120905092915050565b60006fffffffffffffffffffffffffffffffff8316808311156142f4576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fc9836143028660801c90565b0184830361406d565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c9080851015614365576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa9050806143a8576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b84176136d6565b600081611ee08160046142a5565b6040518060006143d5846020840161451f565b6fffffffffffffffffffffffffffffffff16601f8101601f1916830160200160405290915250919050565b6060824710156144785760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161106e565b600080866001600160a01b031685876040516144949190615072565b60006040518083038185875af1925050503d80600081146144d1576040519150601f19603f3d011682016040523d82523d6000602084013e6144d6565b606091505b50915091506136d6878383876145c3565b600060856fffffffffffffffffffffffffffffffff83166140e8565b6000611ee08383601461379d565b60006105e68282601161379d565b6040516000908083101561455f576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b85518110156145b657600086828151811061458057614580614c9c565b602002602001015190506145968184880161430b565b506fffffffffffffffffffffffffffffffff169190910190600101614563565b50608084901b8117610bc4565b6060831561463257825160000361462b576001600160a01b0385163b61462b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161106e565b5081612fc9565b612fc983838151156146475781518083602001fd5b8060405162461bcd60e51b815260040161106e91906149f5565b6001600160a01b038116811461108057600080fd5b60006020828403121561468857600080fd5b8135611ee081614661565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051600681106146d4576146d4614693565b825260208181015163ffffffff9081169184019190915260409182015116910152565b606081016105e682846146c2565b60006020828403121561471757600080fd5b5035919050565b60005b83811015614739578181015183820152602001614721565b50506000910152565b6000815180845261475a81602086016020860161471e565b601f01601f19169290920160200192915050565b6040815260006147816040830185614742565b8281036020840152610bc48185614742565b6001600160a01b038316815260808101611ee060208301846146c2565b63ffffffff8116811461108057600080fd5b6000602082840312156147d457600080fd5b8135611ee0816147b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614837576148376147df565b604052919050565b600067ffffffffffffffff821115614859576148596147df565b50601f01601f191660200190565b600082601f83011261487857600080fd5b813561488b6148868261483f565b61480e565b8181528460208386010111156148a057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156148d557600080fd5b85356148e0816147b0565b94506020868101359450604087013567ffffffffffffffff8082111561490557600080fd5b6149118a838b01614867565b955060608901359450608089013591508082111561492e57600080fd5b818901915089601f83011261494257600080fd5b813581811115614954576149546147df565b8060051b915061496584830161480e565b818152918301840191848101908c84111561497f57600080fd5b938501935b838510156149bf57843592506fffffffffffffffffffffffffffffffff831683146149af5760008081fd5b8282529385019390850190614984565b8096505050505050509295509295909350565b6003811061108057611080614693565b602081016149ef836149d2565b91905290565b602081526000611ee06020830184614742565b60008083601f840112614a1a57600080fd5b50813567ffffffffffffffff811115614a3257600080fd5b6020830191508360208260051b8501011115614a4d57600080fd5b9250929050565b60008060208385031215614a6757600080fd5b823567ffffffffffffffff811115614a7e57600080fd5b614a8a85828601614a08565b90969095509350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015614b1c578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805115158452870151878401879052614b0987850182614742565b9588019593505090860190600101614abd565b509098975050505050505050565b60008060408385031215614b3d57600080fd5b8235614b48816147b0565b91506020830135614b58816147b0565b809150509250929050565b600080600080600080600060a0888a031215614b7e57600080fd5b873567ffffffffffffffff80821115614b9657600080fd5b614ba28b838c01614867565b985060208a0135915080821115614bb857600080fd5b614bc48b838c01614a08565b909850965060408a0135915080821115614bdd57600080fd5b614be98b838c01614a08565b909650945060608a0135915060ff82168214614c0457600080fd5b9092506080890135908082168214614c1b57600080fd5b508091505092959891949750929550565b81516060820190614c3c816149d2565b80835250602083015164ffffffffff8082166020850152806040860151166040850152505092915050565b600060208284031215614c7957600080fd5b813567ffffffffffffffff811115614c9057600080fd5b612fc984828501614867565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215614cdd57600080fd5b815167ffffffffffffffff811115614cf457600080fd5b8201601f81018413614d0557600080fd5b8051614d136148868261483f565b818152856020838501011115614d2857600080fd5b610bc482602083016020860161471e565b600060208284031215614d4b57600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614d8657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614dc557600080fd5b83018035915067ffffffffffffffff821115614de057600080fd5b602001915036819003821315614a4d57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105e6576105e6614e05565b64ffffffffff818116838216019080821115614e6557614e65614e05565b5092915050565b600060608284031215614e7e57600080fd5b6040516060810181811067ffffffffffffffff82111715614ea157614ea16147df565b8060405250809150825160068110614eb857600080fd5b81526020830151614ec8816147b0565b60208201526040830151614edb816147b0565b6040919091015292915050565b600060608284031215614efa57600080fd5b611ee08383614e6c565b60008060808385031215614f1757600080fd5b8251614f2281614661565b9150614f318460208501614e6c565b90509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f6b57614f6b614e05565b5060010190565b63ffffffff828116828216039080821115614e6557614e65614e05565b600063ffffffff8089168352808816602084015286604084015285606084015280851660808401525060c060a083015261373d60c0830184614742565b80516020808301519190811015610c75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600063ffffffff8087168352808616602084015250836040830152608060608301526131fc6080830184614742565b60006020828403121561504f57600080fd5b81518015158114611ee057600080fd5b808201808211156105e6576105e6614e05565b60008251614d8681846020870161471e56fea26469706673582212202e653d4398ba9a9fe481cea5698ede916ac183b506c601fbcb3cfbbed9058d0764736f6c63430008110033","runtime-code":"0x608060405234801561001057600080fd5b50600436106101da5760003560e01c80637622f78d11610104578063a554d1e3116100a2578063e2f006f711610071578063e2f006f714610562578063e30c397814610575578063f2fde38b14610586578063fb0e722b1461059957600080fd5b8063a554d1e3146104f0578063d0dd0675146104f8578063daa74a9e1461052f578063dfadd81a1461054257600080fd5b80638d3638f4116100de5780638d3638f4146104925780638da5cb5b146104b95780639498bd71146104ca578063a2155c34146104dd57600080fd5b80637622f78d1461043857806379ba509714610477578063883099bc1461047f57600080fd5b8063409891521161017c57806360fc84661161014b57806360fc8466146103d457806361169218146103f4578063715018a614610409578063717b86381461041157600080fd5b806340989152146102dc5780634f1275671461033c57806354fd4d501461036b57806355252dd1146103cc57600080fd5b8063305b29ee116101b8578063305b29ee1461024a57806339fe2736146102865780633c6cf473146102a95780633cf7b120146102c957600080fd5b806328f3fac9146101df57806329be4db2146102085780632de5aaf714610229575b600080fd5b6101f26101ed366004614676565b6105c0565b6040516101ff91906146f7565b60405180910390f35b61021b610216366004614705565b6105ec565b6040516101ff92919061476e565b61023c610237366004614705565b6108fa565b6040516101ff929190614793565b6102716102583660046147c2565b6101616020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101ff565b6102996102943660046148bd565b610928565b60405190151581526020016101ff565b6102bc6102b7366004614705565b610bcd565b6040516101ff91906149e2565b61012f545b6040519081526020016101ff565b610160546103129064ffffffffff80821691650100000000008104909116906a0100000000000000000000900463ffffffff1683565b6040805164ffffffffff948516815293909216602084015263ffffffff16908201526060016101ff565b61027161034a366004614705565b60009081526101306020526040902054640100000000900463ffffffff1690565b604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516101ff91906149f5565b6102ce610c7b565b6103e76103e2366004614a54565b610d5f565b6040516101ff9190614a96565b610407610402366004614b2a565b610eca565b005b610407610fe6565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ff565b610407610ff0565b61040761048d366004614b63565b611083565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b6033546001600160a01b031661045f565b6104076104d8366004614705565b611648565b6104076104eb366004614b2a565b6118ff565b610299611b43565b61050b6105063660046147c2565b611d7b565b604080516bffffffffffffffffffffffff90931683526020830191909152016101ff565b6103bf61053d366004614705565b611e48565b6105556105503660046147c2565b611ee7565b6040516101ff9190614c2c565b610299610570366004614c67565b611f7b565b6065546001600160a01b031661045f565b610407610594366004614676565b611f8e565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b60408051606081018252600080825260208201819052918101919091526105e68261209e565b92915050565b61012f546060908190831061062d576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061012f848154811061064357610643614c9c565b600091825260208083209091015480835261013082526040808420815160e081018352815463ffffffff8082168352640100000000820481169683019690965264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909516608082015276010000000000000000000000000000000000000000000090940490911660a08401526001015460c08301526101628054919450919291908790811061071c5761071c614c9c565b90600052602060002090600202016040518060400160405290816000820154815260200160018201548152505090506107ee8382602001518460200151856040015186606001516040805160208101969096528581019490945260e09290921b7fffffffff0000000000000000000000000000000000000000000000000000000016606085015260d890811b7fffffffffff000000000000000000000000000000000000000000000000000000908116606486015291901b1660698301528051604e818403018152606e909201905290565b94507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146108f25760c08201516040517fddeffa6600000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ddeffa6690602401600060405180830381865afa1580156108c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108ef9190810190614ccb565b93505b505050915091565b6040805160608101825260008082526020820181905291810182905261091f8361215e565b91509150915091565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461098c576040517fdbc2fa8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109958661221c565b156109cc576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109d586612251565b15610a0c576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a1785612328565b90506000610a248261233b565b63ffffffff808a166000908152610161602052604090205491925090811690821611610a7c576040517f7b7fd2c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88811660009081526101616020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016918316919091179055610acb82898961234d565b6101626040518060400160405280878152602001610ae8856125f0565b905281546001818101845560009384526020808520845160029094020192835590920151910155610b17611b43565b9050610b2481878b612601565b80516101608054602084015160409094015163ffffffff166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff64ffffffffff95861665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000090931695909416949094171791909116919091179055610bbc858a61274a565b600193505050505b95945050505050565b600081815261012d602090815260408083208151608081018352905463ffffffff80821683526401000000008204169382019390935268010000000000000000830460ff169181019190915269010000000000000000009091046001600160a01b03166060820181905215610c455750600292915050565b600083815261012e60205260409020546001600160a01b031615610c6c5750600192915050565b50600092915050565b50919050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1614610cd8575061015f5490565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5a9190614d39565b905090565b6060818067ffffffffffffffff811115610d7b57610d7b6147df565b604051908082528060200260200182016040528015610dc157816020015b604080518082019091526000815260606020820152815260200190600190039081610d995790505b5091503660005b82811015610ec157858582818110610de257610de2614c9c565b9050602002810190610df49190614d52565b91506000848281518110610e0a57610e0a614c9c565b60200260200101519050306001600160a01b0316838060200190610e2e9190614d90565b604051610e3c929190614df5565b600060405180830381855af49150503d8060008114610e77576040519150601f19603f3d011682016040523d82523d6000602084013e610e7c565b606091505b5060208301521515808252833517610eb8577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610dc8565b50505092915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f2c576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f36612967565b63ffffffff848116600090815260c960205260409020805464ffffffffff84166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff00909116176002179055909150821615610fe15763ffffffff8216600090815260c96020526040902080547fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff0016660100000000000064ffffffffff8416021790555b505050565b610fee612972565b565b60655433906001600160a01b031681146110775760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b611080816129cc565b50565b61108b6129fd565b600061109688612a56565b905060006110a382612a69565b905060006110b083612a7f565b905063ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602083901c6cffffffffffffffffffffffffff1663ffffffff161461112a576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016606083901c64ffffffffff1663ffffffff160361119a576040517f3eeb1dd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815261012d60209081526040918290208251608081018452905463ffffffff80821683526401000000008204169282019290925268010000000000000000820460ff1692810192909252690100000000000000000090046001600160a01b0316606082018190521561123b576040517f0dc1019700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061124c84848d8d8d8d8d612b3f565b905060008160a0015164ffffffffff16426112679190614e34565b905063ffffffff85168110156112a9576040517f5e5728e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080806112c98870ffffffffffffffffffffffffffffffffff16612db1565b60018111156112da576112da614693565b036113135760006112f26112ed8a612de4565b612df0565b905061130088858c84612e31565b915061130b81612fd1565b925050611329565b61132687846113218b612de4565b612fe2565b90505b845163ffffffff1660000361147e5763ffffffff606088901c81168652608085015116602086015260ff8a166040860152801561136b573360608601526113a3565b600086815261012e6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b600086815261012d602090815260409182902087518154928901519389015160608a01516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9092166801000000000000000002919091167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff968716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009096169690931695909517939093171692909217179055611597565b806114b5576040517f589a41b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360608601908152600087815261012d602090815260409182902088518154928a0151938a015194516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9096166801000000000000000002959095167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090951695909216949094179290921791909116919091179190911790555b6040518115158152869063ffffffff60608a901c16907f39c48fd1b2185b07007abc7904a8cdf782cfe449fd0e9bba1c2223a691e15f0b9060200160405180910390a36115ef846000015185602001518885896130f1565b61162d5760408051878152602081018490527f22bd0cccf7173839e6f30c797b419921d48a23b0732d0b120c600a49247d3016910160405180910390a15b505050505050505061163f600160fb55565b50505050505050565b600054610100900460ff16158080156116685750600054600160ff909116105b806116825750303b158015611682575060005460ff166001145b6116f45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161106e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561175257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61175a61320d565b611762613292565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146118985761015f8290556040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b15801561183657600080fd5b505af115801561184a573d6000803e3d6000fd5b50505050611856612967565b610160805464ffffffffff9290921665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff9092169190911790555b80156118fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611961576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061196b612967565b9050600060405180606001604052806001600281111561198d5761198d614693565b815264ffffffffff84166020808301919091526000604092830181905263ffffffff8816815260c99091522081518154929350839282907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156119fa576119fa614693565b0217905550602082810151825460409485015164ffffffffff9081166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff9190931661010002167fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff909116171790915563ffffffff8516600090815260c990915220815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115611ac457611ac4614693565b0217905550602082015181546040909301517fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff90931661010064ffffffffff928316027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff16176601000000000000919093160291909117905550505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1603611b9e5750600090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c229190614d39565b61015f54909150808203611c395760009250505090565b604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff1691810182905290611c859061221c565b15611c9657505061015f5550600090565b611ca38160400151612251565b15611cb2576001935050505090565b60208101514290611cc7906201518090614e47565b64ffffffffff161115611cde576001935050505090565b6040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b158015611d5957600080fd5b505af1158015611d6d573d6000803e3d6000fd5b505050506000935050505090565b63ffffffff818116600090815261016360209081526040808320815160608101835290546bffffffffffffffffffffffff811682526c0100000000000000000000000081049095169281019290925270010000000000000000000000000000000090930464ffffffffff16928101839052909182919015801590611e095750611e07816020015161221c565b155b8015611e1f5750611e1d8160200151612251565b155b15611e425780516040820151909350611e3f9064ffffffffff1642614e34565b91505b50915091565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b03166060808301919091529290919003611ed6575050604080516020810190915260008152919050565b611ee08382613317565b9392505050565b604080516060810182526000808252602082018190529181019190915263ffffffff8216600090815260c96020526040908190208151606081019092528054829060ff166002811115611f3c57611f3c614693565b6002811115611f4d57611f4d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015292915050565b60006105e6611f898361348b565b61349e565b611f96612972565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611fdf6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610d5a465b600063ffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f3220626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b5090565b60408051606081018252600080825260208201819052918101919091526040517f28f3fac90000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000016906328f3fac990602401606060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e69190614ee8565b604080516060810182526000808252602082018190529181018290526040517f2de5aaf7000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632de5aaf790602401608060405180830381865afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190614f04565b60008063ffffffff8316600090815260c9602052604090205460ff16600281111561224957612249614693565b141592915050565b63ffffffff8116600090815260c96020526040808220815160608101909252805483929190829060ff16600281111561228c5761228c614693565b600281111561229d5761229d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015290506000815160028111156122dc576122dc614693565b146122ea5750600092915050565b806020015164ffffffffff166000036123065750600092915050565b60408101516123189061a8c090614e47565b64ffffffffff1642109392505050565b60006105e661233683613749565b61375c565b60006105e660406004845b919061379d565b6000612358846137be565b60008181526101306020526040902054909150760100000000000000000000000000000000000000000000900464ffffffffff16156123c3576040517fa789712900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808463ffffffff1681526020016123e38661233b565b63ffffffff1681526020016123f7866137cc565b64ffffffffff16815260200161240c866137db565b64ffffffffff16815260200161242761012f8054905061201e565b63ffffffff16815260200161243a612967565b64ffffffffff90811682526020918201949094526000838152610130825260408082208451815494860151928601516060870151608088015160a08901518b16760100000000000000000000000000000000000000000000027fffffffffff0000000000ffffffffffffffffffffffffffffffffffffffffffff63ffffffff928316720100000000000000000000000000000000000002167fffffffffff000000000000000000ffffffffffffffffffffffffffffffffffff938d166d0100000000000000000000000000027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff95909d166801000000000000000002949094167fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff978316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909a16929095169190911797909717949094169190911797909717919091169590951791909117845560c09091015160019384015561012f8054938401815590527f232da9e50dad2971456a78fb5cd6ff6b75019984d6e918139ce990999420f979909101555050565b60006105e6602080845b91906137ea565b604080516060810182526000808252602082018190529181019190915250604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff169181019190915261266a612967565b64ffffffffff1681527f000000000000000000000000000000000000000000000000000000000000000063ffffffff9081167f000000000000000000000000000000000000000000000000000000000000000091909116148015906126cd575083155b80156126dc57508261015f5414155b15611ee0576126e9612967565b64ffffffffff16602082015263ffffffff821660408083019190915261015f849055517fc8ba82607c756c8ae67c7e47c27ade0b0718d492495044a1f8619663f26ebaa39061273b9085815260200190565b60405180910390a19392505050565b815160005b8181101561296157600084828151811061276b5761276b614c9c565b602002602001015190506000612790826fffffffffffffffffffffffffffffffff1690565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff16036127cc57505061294f565b63ffffffff81811660009081526101636020908152604091829020825160608101845290546bffffffffffffffffffffffff8082168084526c0100000000000000000000000083049096168385015270010000000000000000000000000000000090910464ffffffffff1693820193909352929085901c909116908103612856575050505061294f565b6040518060600160405280826bffffffffffffffffffffffff1681526020018863ffffffff168152602001612889612967565b64ffffffffff90811690915263ffffffff9485166000908152610163602090815260409182902084518154928601519590930151909316700100000000000000000000000000000000027fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff949097166c01000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009091166bffffffffffffffffffffffff909216919091171791909116939093179092555050505b8061295981614f3a565b91505061274f565b50505050565b6000610d5a426138f4565b6033546001600160a01b03163314610fee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161106e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561108081613971565b600260fb5403612a4f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161106e565b600260fb55565b60006105e6612a6483613749565b6139db565b60006105e6612a7a82601185612346565b613a1c565b600080612a8b83612a69565b90506000612aab8270ffffffffffffffffffffffffffffffffff16612db1565b6001811115612abc57612abc614693565b03612b0057611ee0612ae78270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612af66112ed87612de4565b613a60565b613a86565b611ee0612b268270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612b3a612b3587612de4565b613ad2565b613b13565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526000612bdc600160408b901c68ffffffffffffffffff16612b999190614f72565b63ffffffff168989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060209250613b23915050565b90506000612c2b8260608c901c64ffffffffff168888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250613bcb915050565b600081815261013060209081526040808320815160e081018352815463ffffffff8082168352640100000000820481169583019590955264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909416608082015276010000000000000000000000000000000000000000000090930490911660a0830181905260019091015460c083015290955091925003612d20576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d2b9061221c565b15612d62576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d6d90612251565b15612da4576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050979650505050505050565b6000612dd08270ffffffffffffffffffffffffffffffffff1660801c90565b60ff1660018111156105e6576105e6614693565b600081611ee081613c2b565b6000612dfb82613c42565b61209a576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080612e3d83613c77565b905067ffffffffffffffff602082901c81169085161015612e8a576040517fed43c3a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612e9b612e9885613c93565b90565b90508467ffffffffffffffff165a11612ee0576040517faa6c898500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000606088901c64ffffffffff16604089901c68ffffffffffffffffff16612f07876125f0565b8977ffffffffffffffffffffffffffffffffffffffffffffffff8716612f34612f2f8b613ca2565b613cc5565b604051602401612f4996959493929190614f8f565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f032f287e000000000000000000000000000000000000000000000000000000001790529050612fc36001600160a01b03831667ffffffffffffffff8816600084613d04565b93505050505b949350505050565b60006105e6612e9882602085612346565b600080612fee83613ad2565b90506000613031606087901c64ffffffffff166040805163ffffffff9092166020830152810187905260600160408051601f198184030181529190528390613d36565b905060006130686001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683613e64565b9050805160201415806130ad575061307f83613ea8565b7fffffffff00000000000000000000000000000000000000000000000000000000166130aa82614fcc565b14155b156130e4576040517ff8b4221800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff161461314e57506000610bc4565b8260000361315e57506000610bc4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636b47b3bc87878661319a8988613317565b6040518563ffffffff1660e01b81526004016131b9949392919061500e565b6020604051808303816000875af11580156131d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fc919061503d565b9695505050505050565b600160fb55565b600054610100900460ff1661328a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613eb7565b600054610100900460ff1661330f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613f3d565b600082815261012e60205260409020546060906001600160a01b03168061333f575060608201515b600061012f846020015163ffffffff168154811061335f5761335f614c9c565b6000918252602080832090910154808352610130909152604082205490925061338d9063ffffffff1661215e565b5085516040808801516060808a0151835160e095861b7fffffffff0000000000000000000000000000000000000000000000000000000090811660208301527f000000000000000000000000000000000000000000000000000000000000000090961b9095166024860152602885018c90526048850188905260f89290921b7fff0000000000000000000000000000000000000000000000000000000000000016606885015284811b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116606986015288821b8116607d86015291901b1660918301528051608581840301815260a590920190529091506131fc565b60006105e661349983613749565b613fba565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff166134d083613ffb565b63ffffffff161461350d576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061351883614009565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b031660608201529293509003613596575060009392505050565b805163ffffffff166135a785614018565b63ffffffff161415806135cc5750806040015160ff166135c685614026565b60ff1614155b156135db575060009392505050565b60006135e685614035565b60008181526101306020526040812054919250906136099063ffffffff1661215e565b50905061012f836020015163ffffffff168154811061362a5761362a614c9c565b90600052602060002001548214158061365d5750806001600160a01b031661365187614044565b6001600160a01b031614155b1561366e5750600095945050505050565b600084815261012e60205260409020546001600160a01b0316806136e15783606001516001600160a01b03166136a388614053565b6001600160a01b03161480156136d6575083606001516001600160a01b03166136cb88614060565b6001600160a01b0316145b979650505050505050565b60006136ec88614060565b9050816001600160a01b031661370189614053565b6001600160a01b031614801561373d57506001600160a01b038116158061373d575084606001516001600160a01b0316816001600160a01b0316145b98975050505050505050565b805160009060208301612fc9818361406d565b6000613767826140d0565b61209a576040517feb92662c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806137ab8585856137ea565b602084900360031b1c9150509392505050565b60006105e6816020846125fa565b60006105e66044600584612346565b60006105e66049600584612346565b6000816000036137fc57506000611ee0565b6020821115613837576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416613854838561505f565b111561388c576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b600061389d8660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b600064ffffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201527f3020626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006139e6826140ef565b61209a576040517fd082b2a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600160ff608084901c16111561209a576040517f58ebbfbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6613a7d613a7184612fd1565b60009081526020902090565b612afb846141a4565b600082158015613a94575081155b15613aa1575060006105e6565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506105e6565b6000613add826141b4565b61209a576040517f9d46362800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6826141f0565b6141f0565b815160009082811115613b62576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84915060005b81811015613b9f57613b9583868381518110613b8657613b86614c9c565b6020026020010151898461421b565b9250600101613b68565b50805b83811015613bc157613bb7836000898461421b565b9250600101613ba2565b5050949350505050565b60006101fe600183901b1660408110613c10576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613c1c8787614244565b90506136d68282876006613b23565b60006105e6613c3b60118361505f565b83906142a5565b60006018613c526020604061505f565b613c5c919061505f565b6fffffffffffffffffffffffffffffffff8316101592915050565b60006105e6612e98613c8b6020604061505f565b601885612346565b60006105e660406020846125fa565b60006105e66018613cb56020604061505f565b613c3b919061505f565b906142a5565b60405180613cd6836020830161430b565b506fffffffffffffffffffffffffffffffff83166000601f8201601f19168301602001604052509052919050565b6000846001600160a01b03163b600003613d2057506000612fc9565b600080835160208501868989f195945050505050565b6060613d448251601f161590565b613d7a576040517fd49e9d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160038082526080820190925260009160208201606080368337019050509050613dec613da985613ea8565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091166020820152602401604051602081830303815290604052613749565b81600081518110613dff57613dff614c9c565b602002602001018181525050613e1483613749565b81600181518110613e2757613e27614c9c565b602002602001018181525050613e3c846143b4565b81600281518110613e4f57613e4f614c9c565b602002602001018181525050612fc9816143c2565b6060611ee0838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250614400565b600081611ee0818360046137ea565b600054610100900460ff16613f345760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee336129cc565b600054610100900460ff166132065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b6000613fc5826144e7565b61209a576040517f76b4e13c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e660048084612346565b60006105e660086020846125fa565b60006105e681600484612346565b60006105e66048600184612346565b60006105e660286020846125fa565b60006105e66049835b90614503565b60006105e6605d8361404d565b60006105e660718361404d565b60008061407a838561505f565b905060405181111561408a575060005b806000036140c4576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317612fc9565b6000604e6fffffffffffffffffffffffffffffffff83165b1492915050565b60006fffffffffffffffffffffffffffffffff821661410f60118361505f565b81101561411f5750600092915050565b600061412a84614511565b9050600160ff608083901c161115614146575060009392505050565b600061416c61415483613a1c565b70ffffffffffffffffffffffffffffffffff16612db1565b600181111561417d5761417d614693565b0361419357612fc961418e85613c2b565b613c42565b612fc961419f85613c2b565b6141b4565b60006105e6613b1e602084613cbf565b60006fffffffffffffffffffffffffffffffff821660048110156141db5750600092915050565b611ee06141e9600483614e34565b601f161590565b6000806141fd8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b6000600183831c16810361423a576142338585613a86565b9050612fc9565b6142338486613a86565b6000828260405160200161428792919091825260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015260240190565b60405160208183030381529060405280519060200120905092915050565b60006fffffffffffffffffffffffffffffffff8316808311156142f4576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fc9836143028660801c90565b0184830361406d565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c9080851015614365576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa9050806143a8576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b84176136d6565b600081611ee08160046142a5565b6040518060006143d5846020840161451f565b6fffffffffffffffffffffffffffffffff16601f8101601f1916830160200160405290915250919050565b6060824710156144785760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161106e565b600080866001600160a01b031685876040516144949190615072565b60006040518083038185875af1925050503d80600081146144d1576040519150601f19603f3d011682016040523d82523d6000602084013e6144d6565b606091505b50915091506136d6878383876145c3565b600060856fffffffffffffffffffffffffffffffff83166140e8565b6000611ee08383601461379d565b60006105e68282601161379d565b6040516000908083101561455f576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b85518110156145b657600086828151811061458057614580614c9c565b602002602001015190506145968184880161430b565b506fffffffffffffffffffffffffffffffff169190910190600101614563565b50608084901b8117610bc4565b6060831561463257825160000361462b576001600160a01b0385163b61462b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161106e565b5081612fc9565b612fc983838151156146475781518083602001fd5b8060405162461bcd60e51b815260040161106e91906149f5565b6001600160a01b038116811461108057600080fd5b60006020828403121561468857600080fd5b8135611ee081614661565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051600681106146d4576146d4614693565b825260208181015163ffffffff9081169184019190915260409182015116910152565b606081016105e682846146c2565b60006020828403121561471757600080fd5b5035919050565b60005b83811015614739578181015183820152602001614721565b50506000910152565b6000815180845261475a81602086016020860161471e565b601f01601f19169290920160200192915050565b6040815260006147816040830185614742565b8281036020840152610bc48185614742565b6001600160a01b038316815260808101611ee060208301846146c2565b63ffffffff8116811461108057600080fd5b6000602082840312156147d457600080fd5b8135611ee0816147b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614837576148376147df565b604052919050565b600067ffffffffffffffff821115614859576148596147df565b50601f01601f191660200190565b600082601f83011261487857600080fd5b813561488b6148868261483f565b61480e565b8181528460208386010111156148a057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156148d557600080fd5b85356148e0816147b0565b94506020868101359450604087013567ffffffffffffffff8082111561490557600080fd5b6149118a838b01614867565b955060608901359450608089013591508082111561492e57600080fd5b818901915089601f83011261494257600080fd5b813581811115614954576149546147df565b8060051b915061496584830161480e565b818152918301840191848101908c84111561497f57600080fd5b938501935b838510156149bf57843592506fffffffffffffffffffffffffffffffff831683146149af5760008081fd5b8282529385019390850190614984565b8096505050505050509295509295909350565b6003811061108057611080614693565b602081016149ef836149d2565b91905290565b602081526000611ee06020830184614742565b60008083601f840112614a1a57600080fd5b50813567ffffffffffffffff811115614a3257600080fd5b6020830191508360208260051b8501011115614a4d57600080fd5b9250929050565b60008060208385031215614a6757600080fd5b823567ffffffffffffffff811115614a7e57600080fd5b614a8a85828601614a08565b90969095509350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015614b1c578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805115158452870151878401879052614b0987850182614742565b9588019593505090860190600101614abd565b509098975050505050505050565b60008060408385031215614b3d57600080fd5b8235614b48816147b0565b91506020830135614b58816147b0565b809150509250929050565b600080600080600080600060a0888a031215614b7e57600080fd5b873567ffffffffffffffff80821115614b9657600080fd5b614ba28b838c01614867565b985060208a0135915080821115614bb857600080fd5b614bc48b838c01614a08565b909850965060408a0135915080821115614bdd57600080fd5b614be98b838c01614a08565b909650945060608a0135915060ff82168214614c0457600080fd5b9092506080890135908082168214614c1b57600080fd5b508091505092959891949750929550565b81516060820190614c3c816149d2565b80835250602083015164ffffffffff8082166020850152806040860151166040850152505092915050565b600060208284031215614c7957600080fd5b813567ffffffffffffffff811115614c9057600080fd5b612fc984828501614867565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215614cdd57600080fd5b815167ffffffffffffffff811115614cf457600080fd5b8201601f81018413614d0557600080fd5b8051614d136148868261483f565b818152856020838501011115614d2857600080fd5b610bc482602083016020860161471e565b600060208284031215614d4b57600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614d8657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614dc557600080fd5b83018035915067ffffffffffffffff821115614de057600080fd5b602001915036819003821315614a4d57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105e6576105e6614e05565b64ffffffffff818116838216019080821115614e6557614e65614e05565b5092915050565b600060608284031215614e7e57600080fd5b6040516060810181811067ffffffffffffffff82111715614ea157614ea16147df565b8060405250809150825160068110614eb857600080fd5b81526020830151614ec8816147b0565b60208201526040830151614edb816147b0565b6040919091015292915050565b600060608284031215614efa57600080fd5b611ee08383614e6c565b60008060808385031215614f1757600080fd5b8251614f2281614661565b9150614f318460208501614e6c565b90509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f6b57614f6b614e05565b5060010190565b63ffffffff828116828216039080821115614e6557614e65614e05565b600063ffffffff8089168352808816602084015286604084015285606084015280851660808401525060c060a083015261373d60c0830184614742565b80516020808301519190811015610c75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600063ffffffff8087168352808616602084015250836040830152608060608301526131fc6080830184614742565b60006020828403121561504f57600080fd5b81518015158114611ee057600080fd5b808201808211156105e6576105e6614e05565b60008251614d8681846020870161471e56fea26469706673582212202e653d4398ba9a9fe481cea5698ede916ac183b506c601fbcb3cfbbed9058d0764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"289833:11494:0:-:0;;;291499:149;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;263591:219;;;;;;;;;;;;;-1:-1:-1;;;263591:219:0;;;;100839:32;;291603:14;291619:13;291634:6;263591:219;291603:14;263591:219;101105:24;101119:8;101105:24;:::i;:::-;101097:32;;;;;;100793:343;255094:22:::1;:20;;;;;:22;;:::i;:::-;255080:36;::::0;;::::1;;::::0;255126:30:::1;;::::0;-1:-1:-1;;;;;;263751:28:0;;::::1;;::::0;263789:14:::1;;::::0;-1:-1:-1;289833:11494:0;;-1:-1:-1;;;;289833:11494:0;102680:98;102722:6;102747:24;:13;:22;;;;;:24;;:::i;:::-;102740:31;;102680:98;:::o;68801:187::-;68857:6;68892:16;68883:25;;;68875:76;;;;-1:-1:-1;;;68875:76:0;;1155:2:1;68875:76:0;;;1137:21:1;1194:2;1174:18;;;1167:30;1233:34;1213:18;;;1206:62;-1:-1:-1;;;1284:18:1;;;1277:36;1330:19;;68875:76:0;;;;;;;;-1:-1:-1;68975:5:0;68801: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:450::-;283:6;291;299;352:2;340:9;331:7;327:23;323:32;320:52;;;368:1;365;358:12;320:52;400:9;394:16;450:10;443:5;439:22;432:5;429:33;419:61;;476:1;473;466:12;419:61;499:5;-1:-1:-1;523:49:1;568:2;553:18;;523:49;:::i;:::-;513:59;;591:49;636:2;625:9;621:18;591:49;:::i;:::-;581:59;;196:450;;;;;:::o;651:297::-;769:12;;816:4;805:16;;;799:23;;769:12;834:16;;831:111;;;928:1;924:6;914;908:4;904:17;901:1;897:25;893:38;886:5;882:50;873:59;;831:111;;651:297;;;:::o;953:402::-;289833:11494:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"289833:11494:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;265499:122;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;296850:880;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;265661:138::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;290904:53::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3341:10:1;3329:23;;;3311:42;;3299:2;3284:18;290904:53:0;3167:192:1;292769:1409:0;;;;;;:::i;:::-;;:::i;:::-;;;6430:14:1;;6423:22;6405:41;;6393:2;6378:18;292769:1409:0;6265:187:1;277015:421:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;296704:99::-;296783:6;:13;296704:99;;;7161:25:1;;;7149:2;7134:18;296704:99:0;7015:177:1;290821:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;7403:12:1;7442:15;;;7424:34;;7494:15;;;;7489:2;7474:18;;7467:43;7558:10;7546:23;7526:18;;;7519:51;7381:2;7366:18;290821:35:0;7197:379:1;276521:139:0;;;;;;:::i;:::-;276591:15;276625:19;;;:9;:19;;;;;:28;;;;;;;276521:139;101142:401;101313:28;;;;;;;;;101326:7;101313:28;;101335:5;101313:28;;;;101142:401;;;;;;;:::i;298748:238::-;;;:::i;98489:1352::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;264546:579::-;;;;;;:::i;:::-;;:::i;:::-;;255388:57;;;:::i;254506:37::-;;;;;262677;;;;;;;;-1:-1:-1;;;;;10508:55:1;;;10490:74;;10478:2;10463:18;262677:37:0;10344:226:1;226826:212:0;;;:::i;272914:3233::-;;;;;;:::i;:::-;;:::i;254389:35::-;;;;;223157:85;223229:6;;-1:-1:-1;;;;;223229:6:0;223157:85;;291790:622;;;;;;:::i;:::-;;:::i;264158:348::-;;;;;;:::i;:::-;;:::i;294527:1754::-;;;:::i;297777:924::-;;;;;;:::i;:::-;;:::i;:::-;;;;12131:26:1;12119:39;;;12101:58;;12190:2;12175:18;;12168:34;;;;12074:18;297777:924:0;11900:308:1;277476:350:0;;;;;;:::i;:::-;;:::i;265839:138::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;276700:275::-;;;;;;:::i;:::-;;:::i;225939:99::-;226018:13;;-1:-1:-1;;;;;226018:13:0;225939:99;;226231:178;;;;;;:::i;:::-;;:::i;262755:30::-;;;;;265499:122;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;265595:19:0;265608:5;265595:12;:19::i;:::-;265588:26;265499:122;-1:-1:-1;;265499:122:0:o;296850:880::-;296987:6;:13;296912:23;;;;296978:22;;296974:52;;297009:17;;;;;;;;;;;;;;296974:52;297036:16;297055:6;297062:5;297055:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;297109:19;;;:9;:19;;;;;;297078:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;297171:19;:26;;297055:13;;-1:-1:-1;297078:50:0;;297055:13;297171:19;297191:5;;297171:26;;;;;;:::i;:::-;;;;;;;;;;;297138:59;;;;;;;;;;;;;;;;;;;;;;;;;;;297220:241;297278:8;297311:9;:18;;;297351:8;:17;;;297396:8;:14;;;297436:8;:14;;;200250:72;;;;;;19017:19:1;;;;19052:12;;;19045:28;;;;19111:3;19107:16;;;;19125:66;19103:89;200219:12:0;19089::1;;19082:111;19316:3;19312:16;;;19212:66;19308:25;;;19294:12;;;19287:47;19368:16;;;19364:25;19350:12;;;19343:47;200250:72:0;;;;;;;;;19406:12:1;;;;200250:72:0;;;200030:299;297220:241;297207:254;;297609:13;297594:28;;:11;:28;;;297590:134;;297695:17;;;;297653:60;;;;;;;;7161:25:1;;;;297669:5:0;-1:-1:-1;;;;;297653:41:0;;;;7134:18:1;;297653:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;297653:60:0;;;;;;;;;;;;:::i;:::-;297638:75;;297590:134;296964:766;;;296850:880;;;:::o;265661:138::-;-1:-1:-1;;;;;;;;265717:13:0;-1:-1:-1;;;;;;;;;;;;;;;265776:16:0;265786:5;265776:9;:16::i;:::-;265769:23;;;;265661:138;;;:::o;292769:1409::-;292979:16;263523:10;-1:-1:-1;;;;;263537:5:0;263523:19;;263519:48;;263551:16;;;;;;;;;;;;;;263519:48;293129:33:::1;293150:11;293129:20;:33::i;:::-;293125:63;;;293171:17;;;;;;;;;;;;;;293125:63;293202:34;293224:11;293202:21;:34::i;:::-;293198:70;;;293245:23;;;;;;;;;;;;;;293198:70;293395:15;293413:30;:10;:28;:30::i;:::-;293395:48;;293518:15;293536:11;:3;:9;:11::i;:::-;293573:33;::::0;;::::1;;::::0;;;:20:::1;:33;::::0;;;;;293518:29;;-1:-1:-1;293573:33:0;;::::1;293561:45:::0;;::::1;;293557:73;;293615:15;;;;;;;;;;;;;;293557:73;293640:33;::::0;;::::1;;::::0;;;:20:::1;:33;::::0;;;;:44;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;293769::::1;293786:3:::0;293640:33;293804:8;293769:16:::1;:44::i;:::-;293823:19;293848:63;;;;;;;;293874:9;293848:63;;;;293895:14;:3;:12;:14::i;:::-;293848:63:::0;;293823:89;;::::1;::::0;;::::1;::::0;;-1:-1:-1;293823:89:0;;;::::1;::::0;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;::::1;::::0;294017:15:::1;:13;:15::i;:::-;293998:34;;294055:51;294070:11;294083:9;294094:11;294055:14;:51::i;:::-;294042:64:::0;;:10:::1;:64:::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;294116:34:::1;294129:7:::0;294138:11;294116:12:::1;:34::i;:::-;294167:4;294160:11;;;;;263577:1;292769:1409:::0;;;;;;;:::o;277015:421::-;277082:20;277144:25;;;:12;:25;;;;;;;;277114:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;277114:55:0;;;;;;;277183:31;277179:251;;-1:-1:-1;277237:21:0;;277015:421;-1:-1:-1;;277015:421:0:o;277179:251::-;277318:1;277279:27;;;:14;:27;;;;;;-1:-1:-1;;;;;277279:27:0;:41;277275:155;;-1:-1:-1;277343:20:0;;277015:421;-1:-1:-1;;277015:421:0:o;277275:155::-;-1:-1:-1;277401:18:0;;277015:421;-1:-1:-1;;277015:421:0:o;277275:155::-;277104:332;277015:421;;;:::o;298748:238::-;298796:7;298907:13;298892:28;;:11;:28;;;:87;;-1:-1:-1;298965:14:0;;;298748:238::o;298892:87::-;298937:12;-1:-1:-1;;;;;298923:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;298885:94;;298748:238;:::o;98489:1352::-;98549:27;98605:5;;98641:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;98641:20:0;;;;;;;;;;;;;;;;98627:34;;98671:19;98705:9;98700:1135;98724:6;98720:1;:10;98700:1135;;;98755:5;;98761:1;98755:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;98747:16;;98777:20;98800:11;98812:1;98800:14;;;;;;;;:::i;:::-;;;;;;;98777:37;;99157:4;-1:-1:-1;;;;;99149:26:0;99176:5;:14;;;;;;;;:::i;:::-;99149:42;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;99128:17:0;;;99111:80;;;;;;99464:19;;99461:38;99451:301;;99628:66;99622:4;99615:80;99729:4;99723;99716:18;99451:301;-1:-1:-1;99807:3:0;;98700:1135;;;;98578:1263;;98489:1352;;;;:::o;264546:579::-;263406:10;-1:-1:-1;;;;;263420:12:0;263406:26;;263402:62;;263441:23;;;;;;;;;;;;;;263402:62;264711:17:::1;264731:29;:27;:29::i;:::-;264770:23;::::0;;::::1;;::::0;;;:9:::1;:23;::::0;;;;:50;;264830:47:::1;::::0;::::1;::::0;::::1;::::0;;;;;264801:19:::1;264830:47:::0;;;264711:49;;-1:-1:-1;264973:15:0;::::1;::::0;264969:150:::1;;265004:21;::::0;::::1;265033:16;265004:21:::0;;;:9:::1;:21;::::0;;;;:45;;265063;;;::::1;::::0;::::1;;;::::0;;264969:150:::1;264636:489;264546:579:::0;;:::o;255388:57::-;223050:13;:11;:13::i;:::-;255388:57::o;226826:212::-;226018:13;;194999:10;;-1:-1:-1;;;;;226018:13:0;226925:24;;226917:78;;;;-1:-1:-1;;;226917:78:0;;15774:2:1;226917:78:0;;;15756:21:1;15813:2;15793:18;;;15786:30;15852:34;15832:18;;;15825:62;15923:11;15903:18;;;15896:39;15952:19;;226917:78:0;;;;;;;;;227005:26;227024:6;227005:18;:26::i;:::-;226868:170;226826:212::o;272914:3233::-;192930:21;:19;:21::i;:::-;273205:15:::1;273223:26;:10;:24;:26::i;:::-;273205:44;;273259:13;273275:16;:7;:14;:16::i;:::-;273259:32;;273301:15;273319:14;:7;:12;:14::i;:::-;273301:32:::0;-1:-1:-1;273399:35:0::1;273423:11;273399:35;149262:5:::0;153035:42;;;;;273399:35:::1;;;273395:76;;273443:28;;;;;;;;;;;;;;273395:76;273541:30;273560:11;273541:30;149045:6:::0;152480:37;;;;;273541:30:::1;;::::0;273537:66:::1;;273580:23;;;;;;;;;;;;;;273537:66;273672:27;273702:21:::0;;;:12:::1;:21;::::0;;;;;;;;273672:51;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;::::1;;::::0;;::::1;::::0;;;;;;::::1;;;::::0;;;;;;;;;::::1;-1:-1:-1::0;;;;;273672:51:0::1;::::0;;;;;;273737:31;273733:61:::1;;273777:17;;;;;;;;;;;;;;273733:61;273837:28;273868:70;273886:6;273894:7;273903:11;;273916:9;;273927:10;273868:17;:70::i;:::-;273837:101;;273997:21;274039:8;:20;;;274021:38;;:15;:38;;;;:::i;:::-;273997:62:::0;-1:-1:-1;274073:41:0::1;::::0;;;::::1;274069:79;;;274123:25;;;;;;;;;;;;;;274069:79;274158:18;::::0;;274261:13:::1;:6;:11;;;:13::i;:::-;:33;;;;;;;;:::i;:::-;::::0;274257:527:::1;;274397:23;274423:34;:14;:7;:12;:14::i;:::-;:32;:34::i;:::-;274397:60;;274481:65;274501:6;274509:13;274524:8;274534:11;274481:19;:65::i;:::-;274471:75;;274585:18;:11;:16;:18::i;:::-;274560:44;;274296:319;274257:527;;;274712:61;274735:6;274743:13;274758:14;:7;:12;:14::i;:::-;274712:22;:61::i;:::-;274702:71;;274257:527;274797:15:::0;;:20:::1;;:15;:20:::0;274793:1020:::1;;274937:33;149045:6:::0;152480:37;;;274937:33;;;;275005:14:::1;::::0;::::1;::::0;274984:35:::1;:18;::::0;::::1;:35:::0;275033:32:::1;::::0;::::1;:19;::::0;::::1;:32:::0;275079:314;::::1;;;275224:10;275204:17;::::0;::::1;:30:::0;275079:314:::1;;;275342:23;::::0;;;:14:::1;:23;::::0;;;;:36;;;::::1;275368:10;275342:36;::::0;;275079:314:::1;275406:21;::::0;;;:12:::1;:21;::::0;;;;;;;;:32;;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;275406:32:0::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;::::1;::::0;;274793:1020:::1;;;275474:7;275469:36;;275490:15;;;;;;;;;;;;;;275469:36;275746:10;275726:17;::::0;::::1;:30:::0;;;275770:21:::1;::::0;;;:12:::1;:21;::::0;;;;;;;;:32;;;;;;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;;;;275770:32:0::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;;;::::1;::::0;;274793:1020:::1;275827:43;::::0;6430:14:1;;6423:22;6405:41;;275853:7:0;;275827:43:::1;149045:6:::0;152480:37;;;275827:43;;::::1;::::0;6393:2:1;6378:18;275827:43:0::1;;;;;;;275885:84;275898:8;:20;;;275920:8;:17;;;275939:7;275948:10;275960:8;275885:12;:84::i;:::-;275880:261;;276097:33;::::0;;16478:25:1;;;16534:2;16519:18;;16512:34;;;276097:33:0::1;::::0;16451:18:1;276097:33:0::1;;;;;;;275880:261;273121:3026;;;;;;;;192972:20:::0;192212:1;193478:7;:22;193298:209;192972:20;272914:3233;;;;;;;:::o;291790:622::-;157233:19;157256:13;;;;;;157255:14;;157301:34;;;;-1:-1:-1;157319:12:0;;157334:1;157319:12;;;;:16;157301:34;157300:108;;;-1:-1:-1;157380:4:0;90357:19;:23;;;157341:66;;-1:-1:-1;157390:12:0;;;;;:17;157341:66;157279:201;;;;-1:-1:-1;;;157279:201:0;;16759:2:1;157279:201:0;;;16741:21:1;16798:2;16778:18;;;16771:30;16837:34;16817:18;;;16810:62;16908:16;16888:18;;;16881:44;16942:19;;157279:201:0;16557:410:1;157279:201:0;157490:12;:16;;;;157505:1;157490:16;;;157516:65;;;;157550:13;:20;;;;;;;;157516:65;291920:21:::1;:19;:21::i;:::-;291990:24;:22;:24::i;:::-;292093:13;292078:28;;:11;:28;;;292074:237;;292122:14;:26:::0;;;292162:68:::1;::::0;;;;::::1;::::0;::::1;7161:25:1::0;;;292192:12:0::1;-1:-1:-1::0;;;;;292162:57:0::1;::::0;::::1;::::0;7134:18:1;;292162:68:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;292271:29;:27;:29::i;:::-;292244:10;:56:::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;292074:237:::1;157605:14:::0;157601:99;;;157651:5;157635:21;;;;;;157675:14;;-1:-1:-1;17124:36:1;;157675:14:0;;17112:2:1;17097:18;157675:14:0;;;;;;;157601:99;157223:483;291790:622;:::o;264158:348::-;263406:10;-1:-1:-1;;;;;263420:12:0;263406:26;;263402:62;;263441:23;;;;;;;;;;;;;;263402:62;264254:15:::1;264272:29;:27;:29::i;:::-;264254:47;;264311:27;264341:77;;;;;;;;264362:19;264341:77;;;;;;;;:::i;:::-;::::0;;::::1;::::0;::::1;;::::0;;::::1;::::0;;;;-1:-1:-1;264341:77:0;;;;;;;264428:21:::1;::::0;::::1;::::0;;:9:::1;:21:::0;;;;:30;;;;264311:107;;-1:-1:-1;264311:107:0;;264428:21;;:30;::::1;::::0;;::::1;::::0;::::1;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;264428:30:0::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;::::1;;;::::0;;;;;;::::1;::::0;;;264468:22:::1;::::0;::::1;264428:30;264468:22:::0;;;:9:::1;:22:::0;;;;:31;;;;264493:6;;264468:22;:31;:22;;:31;::::1;264428:30;264468:31:::0;::::1;::::0;::::1;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;264468:31:0::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;;::::1;;::::0;;::::1;;::::0;;;;;;;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;;;;264158:348:0:o;294527:1754::-;294568:16;294712:13;294697:28;;:11;:28;;;294693:46;;-1:-1:-1;294734:5:0;;294527:1754::o;294693:46::-;294749:15;294781:12;-1:-1:-1;;;;;294767:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;294834:14;;294749:57;;-1:-1:-1;294938:18:0;;;294934:36;;294965:5;294958:12;;;;294527:1754;:::o;294934:36::-;294980:44;;;;;;;;295014:10;294980:44;;;;;;;;;;;;;;;;;;;;;;;;;;;295202:40;;:20;:40::i;:::-;295198:202;;;-1:-1:-1;;295339:14:0;:24;-1:-1:-1;295384:5:0;;294527:1754::o;295198:202::-;295636:41;295658:6;:18;;;295636:21;:41::i;:::-;295632:151;;;295768:4;295761:11;;;;;294527:1754;:::o;295632:151::-;295853:20;;;;295907:15;;295853:51;;27349:6;;295853:51;:::i;:::-;:69;;;295849:179;;;296013:4;296006:11;;;;;294527:1754;:::o;295849:179::-;296186:66;;;;;;;;7161:25:1;;;296216:12:0;-1:-1:-1;;;;;296186:57:0;;;;7134:18:1;;296186:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;296269:5;296262:12;;;;;294527:1754;:::o;297777:924::-;297921:22;;;;297835:15;297921:22;;;:14;:22;;;;;;;;297884:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;297835:15;;;;297884:59;298276:30;;;;:94;;;298323:47;298344:13;:25;;;298323:20;:47::i;:::-;298322:48;298276:94;:159;;;;;298387:48;298409:13;:25;;;298387:21;:48::i;:::-;298386:49;298276:159;298259:315;;;298470:21;;298538:25;;;;298470:21;;-1:-1:-1;298520:43:0;;;;:15;:43;:::i;:::-;298505:58;;298259:315;297874:827;297777:924;;;:::o;277476:350::-;277580:27;277610:25;;;:12;:25;;;;;;;;277580:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;277580:55:0;277544:24;277580:55;;;;;;;277544:24;277580:55;;277733:20;;277729:35;;-1:-1:-1;;277755:9:0;;;;;;;;;-1:-1:-1;277755:9:0;;;277476:350;-1:-1:-1;277476:350:0:o;277729:35::-;277781:38;277797:11;277810:8;277781:15;:38::i;:::-;277774:45;277476:350;-1:-1:-1;;;277476:350:0:o;265839:138::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;265949:21:0;;;;;;;:9;:21;;;;;;;265942:28;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;265839:138;-1:-1:-1;;265839:138:0:o;276700:275::-;276773:12;276924:44;276940:27;:11;:25;:27::i;:::-;276924:15;:44::i;226231:178::-;223050:13;:11;:13::i;:::-;226320::::1;:24:::0;;-1:-1:-1;;;;;226320:24:0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;226384:7:::1;223229:6:::0;;-1:-1:-1;;;;;223229:6:0;;223157:85;226384:7:::1;-1:-1:-1::0;;;;;226359:43:0::1;;;;;;;;;;;226231:178:::0;:::o;102680:98::-;102722:6;102747:24;:13;68801:187;68857:6;68892:16;68883:25;;;68875:76;;;;-1:-1:-1;;;68875:76:0;;17552:2:1;68875:76:0;;;17534:21:1;17591:2;17571:18;;;17564:30;17630:34;17610:18;;;17603:62;17701:8;17681:18;;;17674:36;17727:19;;68875:76:0;17350:402:1;68875:76:0;-1:-1:-1;68975:5:0;68801:187::o;266370:150::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;266467:46:0;;;;;-1:-1:-1;;;;;10508:55:1;;;266467:46:0;;;10490:74:1;266481:12:0;266467:39;;;;10463:18:1;;266467:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;266641:166::-;-1:-1:-1;;;;;;;;266698:13:0;-1:-1:-1;;;;;;;;;;;;;;;266757:43:0;;;;;;;;7161:25:1;;;266771:12:0;-1:-1:-1;;;;;266757:36:0;;;;7134:18:1;;266757:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;267192:150::-;267265:4;;267288:22;;;;;;;:9;:22;;;;;:27;;;:47;;;;;;;;:::i;:::-;;;;267192:150;-1:-1:-1;;267192:150:0:o;267795:524::-;267915:22;;;267869:4;267915:22;;;:9;:22;;;;;;267885:52;;;;;;;;;;267869:4;;267885:52;267915:22;267885:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;267885:52:0;268016:11;;:31;;;;;;;;:::i;:::-;;268012:49;;-1:-1:-1;268056:5:0;;267795:524;-1:-1:-1;;267795:524:0:o;268012:49::-;268134:6;:15;;;:20;;268153:1;268134:20;268130:38;;-1:-1:-1;268163:5:0;;267795:524;-1:-1:-1;;267795:524:0:o;268130:38::-;268270:17;;;;:42;;27688:8;;268270:42;:::i;:::-;268252:60;;:15;:60;;267795:524;-1:-1:-1;;;267795:524:0:o;200480:141::-;200552:11;200582:32;200600:13;:7;:11;:13::i;:::-;200582:17;:32::i;203288:218::-;203343:6;203441:57;199114:2;203495:1;203441:3;:12;:22;:57;:22;:57::i;282226:643::-;282326:12;282341:14;:3;:12;:14::i;:::-;282369:15;;;;:9;:15;;;;;:27;:15;;-1:-1:-1;282369:27:0;;;;;:32;282365:69;;282410:24;;;;;;;;;;;;;;282365:69;282531:304;;;;;;;;282571:11;282531:304;;;;;;282606:11;:3;:9;:11::i;:::-;282531:304;;;;;;282638:17;:3;:15;:17::i;:::-;282531:304;;;;;;282676:15;:3;:13;:15::i;:::-;282531:304;;;;;;282712:24;:6;:13;;;;:22;:24::i;:::-;282531:304;;;;;;282763:29;:27;:29::i;:::-;282531:304;;;;;;;;;;;;;;-1:-1:-1;282513:15:0;;;:9;:15;;;;;;:322;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;282845:6;:17;;;;;;;;;;;;;;-1:-1:-1;;282226:643:0:o;202778:149::-;202836:7;202862:58;199066:2;;202862:3;:12;:18;:58;:18;:58::i;299524:869::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;299686:19:0;;;;;;;;299695:10;299686:19;;;;;;;;;;;;;;;;;;;;;;;;;;;299798:29;:27;:29::i;:::-;299776:51;;;;300100:11;:28;;;;300115:13;300100:28;;;;;;;;:44;;;300133:11;300132:12;300100:44;:75;;;;;300166:9;300148:14;;:27;;300100:75;300096:291;;;300214:29;:27;:29::i;:::-;300191:52;;:20;;;:52;300257:32;;;:18;;;;:32;;;;300303:14;:26;;;300348:28;;;;;300320:9;7161:25:1;;7149:2;7134:18;;7015:177;300348:28:0;;;;;;;;299524:869;;;;;:::o;300468:857::-;300579:14;;300556:20;300603:716;300627:12;300623:1;:16;300603:716;;;300660:17;300680:7;300688:1;300680:10;;;;;;;;:::i;:::-;;;;;;;300660:30;;300704:13;300720:17;:8;:15;;153350:6;153149:216;300720:17;300704:33;;300821:11;300811:21;;:6;:21;;;300807:35;;300834:8;;;;300807:35;300893:22;;;;300856:34;300893:22;;;:14;:22;;;;;;;;;300856:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;145996:39;;;;;;;;301043:64;;301039:78;;301109:8;;;;;;301039:78;301205:103;;;;;;;;301229:7;301205:103;;;;;;301251:11;301205:103;;;;;;301277:29;:27;:29::i;:::-;301205:103;;;;;;;301164:22;;;;;;;;:14;:22;;;;;;;;;:144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;300603:716:0;300641:3;;;;:::i;:::-;;;;300603:716;;;;300546:779;300468:857;;:::o;102406:107::-;102455:6;102480:26;:15;:24;:26::i;223315:130::-;223229:6;;-1:-1:-1;;;;;223229:6:0;194999:10;223378:23;223370:68;;;;-1:-1:-1;;;223370:68:0;;20222:2:1;223370:68:0;;;20204:21:1;;;20241:18;;;20234:30;20300:34;20280:18;;;20273:62;20352:18;;223370:68:0;20020:356:1;226593:153:0;226682:13;226675:20;;;;;;226705:34;226730:8;226705:24;:34::i;193005:287::-;192255:1;193137:7;;:19;193129:63;;;;-1:-1:-1;;;193129:63:0;;20583:2:1;193129:63:0;;;20565:21:1;20622:2;20602:18;;;20595:30;20661:33;20641:18;;;20634:61;20712:18;;193129:63:0;20381:355:1;193129:63:0;192255:1;193267:7;:18;193005:287::o;257473:129::-;257541:7;257567:28;257581:13;:7;:11;:13::i;:::-;257567;:28::i;260011:186::-;260067:6;260092:98;260114:74;260067:6;25896:2;260114:7;:16;153149:216;260114:74;260092:20;:98::i;259113:522::-;259167:7;259272:14;259289:16;:7;:14;:16::i;:::-;259272:33;-1:-1:-1;259386:16:0;259368:14;:7;:12;;;:14::i;:::-;:34;;;;;;;;:::i;:::-;;259364:265;;259425:79;259446:14;:7;:12;;151371:20;151527:17;;;151643:2;151630:16;;;151319:343;259446:14;259462:41;:34;:14;:7;:12;:14::i;:34::-;:39;:41::i;:::-;259425:20;:79::i;259364:265::-;259542:76;259563:14;:7;:12;;151371:20;151527:17;;;151643:2;151630:16;;;151319:343;259563:14;259579:38;:31;:14;:7;:12;:14::i;:::-;:29;:31::i;:::-;:36;:38::i;285990:1462::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;286457:18:0;286478:82;286516:1;149148:5;152752:36;;;;;286499:18;;;;:::i;:::-;286478:82;;286519:7;286528:11;;286478:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24507:2:0;;-1:-1:-1;286478:20:0;;-1:-1:-1;;286478:82:0:i;:::-;286457:103;-1:-1:-1;286780:20:0;286803:77;286457:103;149045:6;152480:37;;;;;286858:9;;286803:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;286869:10:0;;-1:-1:-1;286803:25:0;;-1:-1:-1;;286803:77:0:i;:::-;286961:23;;;;:9;:23;;;;;;;;286950:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;286780:100:0;;-1:-1:-1;287051:25:0;287047:61;;287085:23;;;;;;;;;;;;;;287047:61;287220:20;;287199:42;;:20;:42::i;:::-;287195:72;;;287250:17;;;;;;;;;;;;;;287195:72;287392:20;;287370:43;;:21;:43::i;:::-;287366:79;;;287422:23;;;;;;;;;;;;;;287366:79;286228:1224;;285990:1462;;;;;;;;;:::o;152028:223::-;152080:11;152215:28;152235:6;152215:28;;148940:6;153936:26;;153757:213;152215:28;152203:41;;;;;;;;;;:::i;260275:145::-;260329:7;260366;260399:14;260366:7;260399:5;:14::i;239842:215::-;239909:11;239937:22;239951:7;239937:13;:22::i;:::-;239932:60;;239968:24;;;;;;;;;;;;;;278243:1395;278386:4;278627:15;278645:21;:11;:19;:21::i;:::-;278627:39;-1:-1:-1;278680:29:0;41913:5;43806:42;;;278680:29;;;;;;278676:58;;;278718:16;;;;;;;;;;;;;;278676:58;278801:17;278821:42;:23;:11;:21;:23::i;:::-;34796:3;34684:125;278821:42;278801:62;;278981:8;278968:21;;:9;:21;278964:53;;278998:19;;;;;;;;;;;;;;278964:53;279113:20;149045:6;152480:37;;;;;149148:5;152752:36;;;;;279297:20;:11;:18;:20::i;:::-;279335:13;279366:15;;;279401:29;:21;:11;:19;:21::i;:::-;:27;:29::i;:::-;279136:318;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;279136:318:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;279560:71:0;-1:-1:-1;;;;;279560:18:0;;:71;;;-1:-1:-1;279136:318:0;279560:18;:71::i;:::-;279553:78;;;;;278243:1395;;;;;;;:::o;241563:188::-;241625:4;241648:96;241668:74;241625:4;26088:2;241668:11;:20;153149:216;279813:1258;279915:4;280001:17;280021:21;:4;:19;:21::i;:::-;280001:41;-1:-1:-1;280118:20:0;280141:62;149045:6;152480:37;;;;;280160:42;;;21754:10:1;21742:23;;;280160:42:0;;;21724::1;21782:18;;21775:34;;;21697:18;;280160:42:0;;;-1:-1:-1;;280160:42:0;;;;;;;;;280141:8;;:18;:62::i;:::-;280118:85;-1:-1:-1;280304:23:0;280330:43;-1:-1:-1;;;;;280338:12:0;280330:34;280118:85;280330:34;:43::i;:::-;280304:69;;280940:10;:17;280961:2;280940:23;;:73;;;;280990:23;:8;:21;:23::i;:::-;280967:46;;:19;280975:10;280967:19;:::i;:::-;:46;;280940:73;280936:107;;;281022:21;;;;;;;;;;;;;;280936:107;-1:-1:-1;281060:4:0;;279813:1258;-1:-1:-1;;;;;;279813:1258:0:o;281333:713::-;281529:4;281631:13;281616:28;;:11;:28;;;281612:46;;-1:-1:-1;281653:5:0;281646:12;;281612:46;281771:10;281785:1;281771:15;281767:33;;-1:-1:-1;281795:5:0;281788:12;;281767:33;281832:5;-1:-1:-1;;;;;281817:33:0;;281881:14;281919:8;281953:10;281990:38;282006:11;282019:8;281990:15;:38::i;:::-;281817:222;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;281810:229;281333:713;-1:-1:-1;;;;;;281333:713:0:o;193298:209::-;192212:1;193478:7;:22;193298:209::o;225554:100::-;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;159320:69:0;225621:26:::1;:24;:26::i;192293:111::-:0;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;159320:69:0;192363:34:::1;:32;:34::i;287554:1088::-:0;287789:21;287813:27;;;:14;:27;;;;;;287676:24;;-1:-1:-1;;;;;287813:27:0;;287850:66;;-1:-1:-1;287899:17:0;;;;287850:66;288003:16;288022:6;288029:8;:18;;;288022:26;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;288091:19;;;:9;:19;;;;;;:31;288022:26;;-1:-1:-1;288081:42:0;;288091:31;;288081:9;:42::i;:::-;-1:-1:-1;288323:15:0;;288480:19;;;;;288607:17;;;;;208044:147;;24824:3:1;24820:16;;;24729:66;24816:25;;;208044:147:0;;;24804:38:1;288366:11:0;24875:16:1;;;24871:25;;;24858:11;;;24851:46;24913:11;;;24906:27;;;24949:12;;;24942:28;;;25008:3;25004:16;;;;25022:66;25000:89;24986:12;;;24979:111;25209:15;;;25109:66;25205:24;;;25191:12;;;25184:46;25264:15;;;25260:24;;25246:12;;;25239:46;25320:15;;;25316:24;25301:13;;;25294:47;208044:147:0;;;;;;;;;25357:13:1;;;;208044:147:0;;25209:15:1;;-1:-1:-1;288275:360:0;207728:470;208339:129;208407:7;208433:28;208447:13;:7;:11;:13::i;:::-;208433;:28::i;283348:1705::-;283410:4;283501:11;283479:33;;:18;:4;:16;:18::i;:::-;:33;;;283475:74;;283521:28;;;;;;;;;;;;;;283475:74;283559:19;283581:18;:4;:16;:18::i;:::-;283609:27;283639:25;;;:12;:25;;;;;;;;283609:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;283609:55:0;;;;;283639:25;;-1:-1:-1;283753:20:0;;283749:38;;-1:-1:-1;283782:5:0;;283348:1705;-1:-1:-1;;;283348:1705:0:o;283749:38::-;283876:15;;283859:32;;:13;:4;:11;:13::i;:::-;:32;;;;:76;;;;283916:8;:19;;;283895:40;;:17;:4;:15;:17::i;:::-;:40;;;;283859:76;283855:94;;;-1:-1:-1;283944:5:0;;283348:1705;-1:-1:-1;;;283348:1705:0:o;283855:94::-;284044:16;284063:19;:4;:17;:19::i;:::-;284093:17;284125:19;;;:9;:19;;;;;:31;284044:38;;-1:-1:-1;284093:17:0;284115:42;;284125:31;;284115:9;:42::i;:::-;284092:65;;;284183:6;284190:8;:18;;;284183:26;;;;;;;;;;:::i;:::-;;;;;;;;;284171:8;:38;;:71;;;;284233:9;-1:-1:-1;;;;;284213:29:0;:16;:4;:14;:16::i;:::-;-1:-1:-1;;;;;284213:29:0;;;284171:71;284167:89;;;-1:-1:-1;284251:5:0;;283348:1705;-1:-1:-1;;;;;283348:1705:0:o;284167:89::-;284330:21;284354:27;;;:14;:27;;;;;;-1:-1:-1;;;;;284354:27:0;;284391:656;;284541:8;:17;;;-1:-1:-1;;;;;284517:41:0;:20;:4;:18;:20::i;:::-;-1:-1:-1;;;;;284517:41:0;;:86;;;;;284586:8;:17;;;-1:-1:-1;;;;;284562:41:0;:20;:4;:18;:20::i;:::-;-1:-1:-1;;;;;284562:41:0;;284517:86;284510:93;283348:1705;-1:-1:-1;;;;;;;283348:1705:0:o;284391:656::-;284847:21;284871:20;:4;:18;:20::i;:::-;284847:44;;284936:13;-1:-1:-1;;;;;284912:37:0;:20;:4;:18;:20::i;:::-;-1:-1:-1;;;;;284912:37:0;;:124;;;;-1:-1:-1;;;;;;284970:27:0;;;;:65;;;285018:8;:17;;;-1:-1:-1;;;;;285001:34:0;:13;-1:-1:-1;;;;;285001:34:0;;284970:65;284905:131;283348:1705;-1:-1:-1;;;;;;;;283348:1705:0:o;110370:569::-;110458:10;;110424:7;;110884:4;110875:14;;110915:17;110875:14;110458:10;110915:5;:17::i;200773:215::-;200840:11;200868:22;200882:7;200868:13;:22::i;:::-;200863:60;;200899:24;;;;;;;;;;;;;;122950:538;123041:7;;123083:29;:7;123097:6;123105;123083:13;:29::i;:::-;123453:2;:11;;;123469:1;123452:18;123426:45;;-1:-1:-1;;122950:538:0;;;;;:::o;202531:149::-;202589:7;202615:58;202589:7;202669:2;202615:3;:12;153149:216;203591:231;203652:6;203750:64;199169:2;203811:1;203750:3;:12;153149:216;203977:226;204036:6;204134:61;199221:2;204192:1;204134:3;:12;153149:216;121258:1334;121345:14;121375:6;121385:1;121375:11;121371:59;;-1:-1:-1;121417:1:0;121402:17;;121371:59;121516:2;121507:6;:11;121503:65;;;121541:16;;;;;;;;;;;;;;121503:65;114663:17;114637:43;;121647:15;121656:6;121647;:15;:::i;:::-;:31;121643:82;;;121701:13;;;;;;;;;;;;;;121643:82;121764:1;121754:11;;;121734:17;121804:13;:7;114296:3;114269:30;;114110:196;121804:13;122551:17;;;122545:24;122262:66;122243:17;;;;;122239:90;;;;122541:35;;121258:1334;-1:-1:-1;;;;121258:1334:0:o;68289:187::-;68345:6;68380:16;68371:25;;;68363:76;;;;-1:-1:-1;;;68363:76:0;;23688:2:1;68363:76:0;;;23670:21:1;23727:2;23707:18;;;23700:30;23766:34;23746:18;;;23739:62;23837:8;23817:18;;;23810:36;23863:19;;68363:76:0;23486:402:1;224382:187:0;224474:6;;;-1:-1:-1;;;;;224490:17:0;;;;;;;;;;;224522:40;;224474:6;;;224490:17;224474:6;;224522:40;;224455:16;;224522:40;224445:124;224382:187;:::o;257752:195::-;257815:7;257839:18;257849:7;257839:9;:18::i;:::-;257834:52;;257866:20;;;;;;;;;;;;;;150889:328;150954:6;150408:21;150379:51;148940:6;153936:26;;;150379:51;;;151015:52;;151051:16;;;;;;;;;;;;;;240685:255;240747:7;240862:71;240883:25;:18;:11;:16;:18::i;:::-;151371:20;151527:17;;;151643:2;151630:16;;;151319:343;240883:25;240910:22;:11;:20;:22::i;130845:287::-;130926:14;130956:23;;:51;;;;-1:-1:-1;130983:24:0;;130956:51;130952:174;;;-1:-1:-1;131030:1:0;131023:8;;130952:174;131079:35;;;;;;24050:19:1;;;24085:12;;;24078:28;;;24122:12;;131079:35:0;;;;;;;;;;;;131069:46;;;;;;131062:53;;;;187136:200;187200:8;187225:19;187236:7;187225:10;:19::i;:::-;187220:54;;187253:21;;;;;;;;;;;;;;188158:115;188214:7;188240:26;:8;:24;:26::i;:17::-;:24;:26::i;128573:900::-;128813:12;;128708:13;;128839:17;;;128835:48;;;128865:18;;;;;;;;;;;;;;128835:48;128901:4;128893:12;;129070:9;129065:189;129089:8;129085:1;:12;129065:189;;;129203:36;129213:5;129220;129226:1;129220:8;;;;;;;;:::i;:::-;;;;;;;129230:5;129237:1;129203:9;:36::i;:::-;129195:44;-1:-1:-1;129099:3:0;;129065:189;;;-1:-1:-1;129351:8:0;129334:123;129365:6;129361:1;:10;129334:123;;;129404:38;129414:5;129429:1;129433:5;129440:1;129404:9;:38::i;:::-;129396:46;-1:-1:-1;129373:3:0;;129334:123;;;;128727:746;128573:900;;;;;;:::o;251357:998::-;251508:7;251865:24;251888:1;251865:24;;;;251991:25;251973:44;;251969:74;;252026:17;;;;;;;;;;;;;;251969:74;252053:16;252072:37;252090:10;252102:6;252072:17;:37::i;:::-;252053:56;;252270:78;252291:13;252306:8;252316:9;24640:1;252270:20;:78::i;261135:127::-;261189:7;261215:40;256534:29;25896:2;261189:7;256534:29;:::i;:::-;261215:7;;:17;:40::i;240129:241::-;240192:4;25991:2;238223:30;26088:2;238173;238223:30;:::i;:::-;238301:31;;;;:::i;:::-;114663:17;114637:43;;240273:31;;;240129:241;-1:-1:-1;;240129:241:0:o;242302:203::-;242367:7;242393:105;242416:80;238223:30;26088:2;238173;238223:30;:::i;:::-;25991:2;242416:11;:20;153149:216;242043:166;242110:7;242136:66;238173:2;242198;242136:11;:20;153149:216;242602:154;242667:7;242693:56;25991:2;238223:30;26088:2;238173;238223:30;:::i;:::-;238301:31;;;;:::i;242693:20::-;:30;;:56::i;111477:1041::-;111723:4;111717:11;;111853:34;111867:7;111882:4;111876:10;;111853:13;:34::i;:::-;-1:-1:-1;114663:17:0;114637:43;;112099:12;115495:2;115479:18;;-1:-1:-1;;115863:20:0;112395;;112417:4;112391:31;112385:4;112378:45;-1:-1:-1;112485:17:0;;111477:1041;;-1:-1:-1;111477:1041:0:o;33799:625::-;33928:12;34017:9;-1:-1:-1;;;;;34017:21:0;;34042:1;34017:26;34013:44;;-1:-1:-1;34052:5:0;34045:12;;34013:44;34406:1;34403;34393:7;34387:14;34380:4;34371:7;34367:18;34357:8;34346:9;34336:8;34331:77;34320:88;33799:625;-1:-1:-1;;;;;33799:625:0:o;186094:610::-;186176:12;186271:25;186282:6;:13;190414:2;190405:11;:16;;190277:151;186271:25;186266:66;;186305:27;;;;;;;;;;;;;;186266:66;186367:16;;;186381:1;186367:16;;;;;;;;;186342:22;;186367:16;;;;;;;;;;-1:-1:-1;186367:16:0;186342:41;;186447:47;186464:23;:8;:21;:23::i;:::-;186447:41;;24296:66:1;24284:79;;;186447:41:0;;;24272:92:1;24380:11;;186447:41:0;;;;;;;;;;;;:45;:47::i;:::-;186436:5;186442:1;186436:8;;;;;;;;:::i;:::-;;;;;;:58;;;;;186560:12;:6;:10;:12::i;:::-;186549:5;186555:1;186549:8;;;;;;;;:::i;:::-;;;;;;:23;;;;;186638:20;:8;:18;:20::i;:::-;186627:5;186633:1;186627:8;;;;;;;;:::i;:::-;;;;;;:31;;;;;186675:22;186691:5;186675:15;:22::i;47865:185::-;47940:12;47971:72;47993:6;48001:4;48007:1;47971:72;;;;;;;;;;;;;;;;;:21;:72::i;189325:255::-;189389:6;189474:8;189507:65;189474:8;189389:6;182036:1;189507:13;:65::i;222820:111::-;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;159320:69:0;222892:32:::1;194999:10:::0;222892:18:::1;:32::i;192410:109::-:0;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;208610:195:0;208673:7;208697:18;208707:7;208697:9;:18::i;:::-;208692:52;;208724:20;;;;;;;;;;;;;;210856:234;210917:6;211015:67;206365:1;;211015:7;:16;153149:216;211151:159;211212:7;211238:65;206419:1;211299:2;211238:7;:16;153149:216;210574:224;210630:6;210728:62;210630:6;210787:1;210728:7;:16;153149:216;211593:236;211653:5;211754:67;206528:2;211818:1;211754:7;:16;153149:216;211372:161;211434:7;211460:66;206474:2;211522;211460:7;:16;153149:216;211896:150;211955:7;211981:58;206581:2;211981:7;:16;:29;;:58::i;212109:158::-;212172:7;212198:62;206638:2;212198:7;:16;153149:216;212330:158;212393:7;212419:62;206695:3;212419:7;:16;153149:216;109490:540;109556:7;;109590:11;109597:4;109590;:11;:::i;:::-;109575:26;;109869:4;109863:11;109857:4;109854:21;109851:38;;;-1:-1:-1;109886:1:0;109851:38;109912:4;109920:1;109912:9;109908:66;;109944:19;;;;;;;;;;;;;;109908:66;124760:3;124752:11;;;124751:20;;109990:33;124427:352;201060:128;201123:4;24980:2;114663:17;114637:43;;201146:13;:35;;201060:128;-1:-1:-1;;201060:128:0:o;258030:803::-;258089:4;114663:17;114637:43;;256534:29;25896:2;258089:4;256534:29;:::i;:::-;258198:6;:20;258194:38;;;-1:-1:-1;258227:5:0;;258030:803;-1:-1:-1;;258030:803:0:o;258194:38::-;258280:20;258303:16;258311:7;258303;:16::i;:::-;258280:39;-1:-1:-1;150408:21:0;150379:51;148940:6;153936:26;;;150379:51;;;258329;;-1:-1:-1;258375:5:0;;258030:803;-1:-1:-1;;;258030:803:0:o;258329:51::-;258550:16;258505:41;:34;258526:12;258505:20;:34::i;:::-;:39;;;:41::i;:::-;:61;;;;;;;;:::i;:::-;;258501:326;;258646:30;:14;258652:7;258646:5;:14::i;:::-;:28;:30::i;258501:326::-;258789:27;:14;258795:7;258789:5;:14::i;:::-;:25;:27::i;241031:163::-;241097:7;241123:64;:55;238121:2;241123:11;:20;153149:216;187496:362;187556:4;114663:17;114637:43;;182036:1;187677:24;;187673:42;;;-1:-1:-1;187710:5:0;;187496:362;-1:-1:-1;;187496:362:0:o;187673:42::-;187815:36;187826:24;182036:1;187826:6;:24;:::i;:::-;190414:2;190405:11;:16;;190277:151;116401:292;116457:14;116483:12;116498:13;:7;114296:3;114269:30;;114110:196;116498:13;114663:17;114637:43;;;;116656:21;;;;;-1:-1:-1;;116401:292:0:o;129855:526::-;129991:14;130196:1;130169:23;;;130168:29;:34;;130164:211;;130251:24;130261:4;130267:7;130251:9;:24::i;:::-;130244:31;;;;130164:211;130340:24;130350:7;130359:4;130340:9;:24::i;233783:220::-;233855:7;233980:5;233987:7;233963:32;;;;;;;;25536:19:1;;;25593:3;25589:16;25607:66;25585:89;25580:2;25571:12;;25564:111;25700:2;25691:12;;25381:328;233963:32:0;;;;;;;;;;;;;233953:43;;;;;;233946:50;;233783:220;;;;:::o;118524:529::-;118599:7;114663:17;114637:43;;118706:13;;;118702:64;;;118742:13;;;;;;;;;;;;;;118702:64;118978:58;119007:6;118991:13;:7;114296:3;114269:30;;114110:196;118991:13;:22;119028:6;119021:4;:13;118978:5;:58::i;125411:842::-;125750:4;125744:11;125489:7;;114663:17;114637:43;;;114296:3;114269:30;;;;125832:12;;;125828:66;;;125867:16;;;;;;;;;;;;;;125828:66;125903:8;126119:4;126111:6;126105:4;126097:6;126091:4;126084:5;126073:51;126066:58;;126148:3;126143:37;;126160:20;;;;;;;;;;;;;;126143:37;124760:3;124752:11;;;124751:20;;126197:49;124427:352;189659:225;189720:7;189806:8;189832:45;189806:8;182036:1;189832:17;:45::i;112738:892::-;112993:4;112987:11;;112830;113158:33;113170:8;113186:4;113180:10;;113158:11;:33::i;:::-;114663:17;114637:43;115495:2;115479:18;;-1:-1:-1;;115863:20:0;113507;;113529:4;113503:31;113497:4;113490:45;113597:17;;;-1:-1:-1;112738:892:0;;-1:-1:-1;112738:892:0:o;49329:446::-;49494:12;49551:5;49526:21;:30;;49518:81;;;;-1:-1:-1;;;49518:81:0;;25916:2:1;49518:81:0;;;25898:21:1;25955:2;25935:18;;;25928:30;25994:34;25974:18;;;25967:62;26065:8;26045:18;;;26038:36;26091:19;;49518:81:0;25714:402:1;49518:81:0;49610:12;49624:23;49651:6;-1:-1:-1;;;;;49651:11:0;49670:5;49677:4;49651:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49609:73;;;;49699:69;49726:6;49734:7;49743:10;49755:12;49699:26;:69::i;208873:152::-;208932:4;25250:3;114663:17;114637:43;;208987:13;114479:208;123751:225;123829:7;123938:29;:7;123956:6;123964:2;123938:17;:29::i;260829:154::-;260885:7;260911:65;:7;260885;25896:2;260911:17;:65::i;126788:1003::-;127058:4;127052:11;126876:7;;127140:14;;;127136:68;;;127177:16;;;;;;;;;;;;;;127136:68;127323:14;127356:9;127351:364;127375:8;:15;127371:1;:19;127351:364;;;127407:15;127425:8;127434:1;127425:11;;;;;;;;:::i;:::-;;;;;;;127407:29;;127587:41;127601:7;127621:6;127610:8;:17;127587:13;:41::i;:::-;-1:-1:-1;114663:17:0;114637:43;127646:23;;;;;127687:3;;127351:364;;;-1:-1:-1;124760:3:0;124752:11;;;124751:20;;127731:53;124427:352;51835:628;52015:12;52043:7;52039:418;;;52070:10;:17;52091:1;52070:22;52066:286;;-1:-1:-1;;;;;90357:19:0;;;52277:60;;;;-1:-1:-1;;;52277:60:0;;26615:2:1;52277:60:0;;;26597:21:1;26654:2;26634:18;;;26627:30;26693:31;26673:18;;;26666:59;26742:18;;52277:60:0;26413:353:1;52277:60:0;-1:-1:-1;52372:10:0;52365:17;;52039:418;52413:33;52421:10;52433:12;53144:17;;:21;53140:379;;53372:10;53366:17;53428:15;53415:10;53411:2;53407:19;53400:44;53140:379;53495:12;53488:20;;-1:-1:-1;;;53488:20:0;;;;;;;;:::i;14:154:1:-;-1:-1:-1;;;;;93:5:1;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:250::-;1521:1;1531:113;1545:6;1542:1;1539:13;1531:113;;;1621:11;;;1615:18;1602:11;;;1595:39;1567:2;1560:10;1531:113;;;-1:-1:-1;;1678:1:1;1660:16;;1653:27;1436:250::o;1691:329::-;1732:3;1770:5;1764:12;1797:6;1792:3;1785:19;1813:76;1882:6;1875:4;1870:3;1866:14;1859:4;1852:5;1848:16;1813:76;:::i;:::-;1934:2;1922:15;-1:-1:-1;;1918:88:1;1909:98;;;;2009:4;1905:109;;1691:329;-1:-1:-1;;1691:329:1:o;2025:377::-;2218:2;2207:9;2200:21;2181:4;2244:44;2284:2;2273:9;2269:18;2261:6;2244:44;:::i;:::-;2336:9;2328:6;2324:22;2319:2;2308:9;2304:18;2297:50;2364:32;2389:6;2381;2364:32;:::i;2407:379::-;-1:-1:-1;;;;;2658:55:1;;2640:74;;2627:3;2612:19;;2723:57;2776:2;2761:18;;2753:6;2723:57;:::i;2791:121::-;2876:10;2869:5;2865:22;2858:5;2855:33;2845:61;;2902:1;2899;2892:12;2917:245;2975:6;3028:2;3016:9;3007:7;3003:23;2999:32;2996:52;;;3044:1;3041;3034:12;2996:52;3083:9;3070:23;3102:30;3126:5;3102:30;:::i;3364:184::-;3416:77;3413:1;3406:88;3513:4;3510:1;3503:15;3537:4;3534:1;3527:15;3553:334;3624:2;3618:9;3680:2;3670:13;;-1:-1:-1;;3666:86:1;3654:99;;3783:18;3768:34;;3804:22;;;3765:62;3762:88;;;3830:18;;:::i;:::-;3866:2;3859:22;3553:334;;-1:-1:-1;3553:334:1:o;3892:245::-;3940:4;3973:18;3965:6;3962:30;3959:56;;;3995:18;;:::i;:::-;-1:-1:-1;4052:2:1;4040:15;-1:-1:-1;;4036:88:1;4126:4;4032:99;;3892:245::o;4142:462::-;4184:5;4237:3;4230:4;4222:6;4218:17;4214:27;4204:55;;4255:1;4252;4245:12;4204:55;4291:6;4278:20;4322:48;4338:31;4366:2;4338:31;:::i;:::-;4322:48;:::i;:::-;4395:2;4386:7;4379:19;4441:3;4434:4;4429:2;4421:6;4417:15;4413:26;4410:35;4407:55;;;4458:1;4455;4448:12;4407:55;4523:2;4516:4;4508:6;4504:17;4497:4;4488:7;4484:18;4471:55;4571:1;4546:16;;;4564:4;4542:27;4535:38;;;;4550:7;4142:462;-1:-1:-1;;;4142:462:1:o;4609:1651::-;4766:6;4774;4782;4790;4798;4851:3;4839:9;4830:7;4826:23;4822:33;4819:53;;;4868:1;4865;4858:12;4819:53;4907:9;4894:23;4926:30;4950:5;4926:30;:::i;:::-;4975:5;-1:-1:-1;4999:2:1;5033:18;;;5020:32;;-1:-1:-1;5103:2:1;5088:18;;5075:32;5126:18;5156:14;;;5153:34;;;5183:1;5180;5173:12;5153:34;5206:49;5247:7;5238:6;5227:9;5223:22;5206:49;:::i;:::-;5196:59;;5302:2;5291:9;5287:18;5274:32;5264:42;;5359:3;5348:9;5344:19;5331:33;5315:49;;5389:2;5379:8;5376:16;5373:36;;;5405:1;5402;5395:12;5373:36;5443:8;5432:9;5428:24;5418:34;;5490:7;5483:4;5479:2;5475:13;5471:27;5461:55;;5512:1;5509;5502:12;5461:55;5548:2;5535:16;5570:2;5566;5563:10;5560:36;;;5576:18;;:::i;:::-;5622:2;5619:1;5615:10;5605:20;;5645:28;5669:2;5665;5661:11;5645:28;:::i;:::-;5707:15;;;5777:11;;;5773:20;;;5738:12;;;;5805:19;;;5802:39;;;5837:1;5834;5827:12;5802:39;5861:11;;;;5881:349;5897:6;5892:3;5889:15;5881:349;;;5979:3;5966:17;5951:32;;6031:34;6022:7;6018:48;6009:7;6006:61;5996:159;;6109:1;6138:2;6134;6127:14;5996:159;6168:20;;;5914:12;;;;6208;;;;5881:349;;;6249:5;6239:15;;;;;;;;4609:1651;;;;;;;;:::o;6642:118::-;6728:1;6721:5;6718:12;6708:46;;6734:18;;:::i;6765:245::-;6915:2;6900:18;;6927:43;6963:6;6927:43;:::i;:::-;6979:25;;;6765:245;:::o;7581:219::-;7730:2;7719:9;7712:21;7693:4;7750:44;7790:2;7779:9;7775:18;7767:6;7750:44;:::i;7987:380::-;8063:8;8073:6;8127:3;8120:4;8112:6;8108:17;8104:27;8094:55;;8145:1;8142;8135:12;8094:55;-1:-1:-1;8168:20:1;;8211:18;8200:30;;8197:50;;;8243:1;8240;8233:12;8197:50;8280:4;8272:6;8268:17;8256:29;;8340:3;8333:4;8323:6;8320:1;8316:14;8308:6;8304:27;8300:38;8297:47;8294:67;;;8357:1;8354;8347:12;8294:67;7987:380;;;;;:::o;8372:474::-;8482:6;8490;8543:2;8531:9;8522:7;8518:23;8514:32;8511:52;;;8559:1;8556;8549:12;8511:52;8599:9;8586:23;8632:18;8624:6;8621:30;8618:50;;;8664:1;8661;8654:12;8618:50;8703:83;8778:7;8769:6;8758:9;8754:22;8703:83;:::i;:::-;8805:8;;8677:109;;-1:-1:-1;8372:474:1;-1:-1:-1;;;;8372:474:1:o;8851:1099::-;9041:4;9070:2;9110;9099:9;9095:18;9140:2;9129:9;9122:21;9163:6;9198;9192:13;9229:6;9221;9214:22;9255:2;9245:12;;9288:2;9277:9;9273:18;9266:25;;9350:2;9340:6;9337:1;9333:14;9322:9;9318:30;9314:39;9388:2;9380:6;9376:15;9409:1;9419:502;9433:6;9430:1;9427:13;9419:502;;;9498:22;;;9522:66;9494:95;9482:108;;9613:13;;9668:9;;9661:17;9654:25;9639:41;;9719:11;;9713:18;9751:15;;;9744:27;;;9794:47;9825:15;;;9713:18;9794:47;:::i;:::-;9899:12;;;;9784:57;-1:-1:-1;;9864:15:1;;;;9455:1;9448:9;9419:502;;;-1:-1:-1;9938:6:1;;8851:1099;-1:-1:-1;;;;;;;;8851:1099:1:o;9955:384::-;10021:6;10029;10082:2;10070:9;10061:7;10057:23;10053:32;10050:52;;;10098:1;10095;10088:12;10050:52;10137:9;10124:23;10156:30;10180:5;10156:30;:::i;:::-;10205:5;-1:-1:-1;10262:2:1;10247:18;;10234:32;10275;10234;10275;:::i;:::-;10326:7;10316:17;;;9955:384;;;;;:::o;10575:1320::-;10730:6;10738;10746;10754;10762;10770;10778;10831:3;10819:9;10810:7;10806:23;10802:33;10799:53;;;10848:1;10845;10838:12;10799:53;10888:9;10875:23;10917:18;10958:2;10950:6;10947:14;10944:34;;;10974:1;10971;10964:12;10944:34;10997:49;11038:7;11029:6;11018:9;11014:22;10997:49;:::i;:::-;10987:59;;11099:2;11088:9;11084:18;11071:32;11055:48;;11128:2;11118:8;11115:16;11112:36;;;11144:1;11141;11134:12;11112:36;11183:85;11260:7;11249:8;11238:9;11234:24;11183:85;:::i;:::-;11287:8;;-1:-1:-1;11157:111:1;-1:-1:-1;11375:2:1;11360:18;;11347:32;;-1:-1:-1;11391:16:1;;;11388:36;;;11420:1;11417;11410:12;11388:36;11459:85;11536:7;11525:8;11514:9;11510:24;11459:85;:::i;:::-;11563:8;;-1:-1:-1;11433:111:1;-1:-1:-1;11648:2:1;11633:18;;11620:32;;-1:-1:-1;11692:4:1;11681:16;;11671:27;;11661:55;;11712:1;11709;11702:12;11661:55;11735:5;;-1:-1:-1;11792:3:1;11777:19;;11764:33;;11828:16;;;11816:29;;11806:57;;11859:1;11856;11849:12;11806:57;;11882:7;11872:17;;;10575:1320;;;;;;;;;;:::o;12435:531::-;12653:13;;12631:2;12616:18;;;12675:39;12653:13;12675:39;:::i;:::-;12741:2;12730:9;12723:21;;12791:4;12783:6;12779:17;12773:24;12816:12;12884:2;12870:12;12866:21;12859:4;12848:9;12844:20;12837:51;12956:2;12948:4;12940:6;12936:17;12930:24;12926:33;12919:4;12908:9;12904:20;12897:63;;;12435:531;;;;:::o;12971:320::-;13039:6;13092:2;13080:9;13071:7;13067:23;13063:32;13060:52;;;13108:1;13105;13098:12;13060:52;13148:9;13135:23;13181:18;13173:6;13170:30;13167:50;;;13213:1;13210;13203:12;13167:50;13236:49;13277:7;13268:6;13257:9;13253:22;13236:49;:::i;13296:184::-;13348:77;13345:1;13338:88;13445:4;13442:1;13435:15;13469:4;13466:1;13459:15;13485:647;13564:6;13617:2;13605:9;13596:7;13592:23;13588:32;13585:52;;;13633:1;13630;13623:12;13585:52;13666:9;13660:16;13699:18;13691:6;13688:30;13685:50;;;13731:1;13728;13721:12;13685:50;13754:22;;13807:4;13799:13;;13795:27;-1:-1:-1;13785:55:1;;13836:1;13833;13826:12;13785:55;13865:2;13859:9;13890:48;13906:31;13934:2;13906:31;:::i;13890:48::-;13961:2;13954:5;13947:17;14001:7;13996:2;13991;13987;13983:11;13979:20;13976:33;13973:53;;;14022:1;14019;14012:12;13973:53;14035:67;14099:2;14094;14087:5;14083:14;14078:2;14074;14070:11;14035:67;:::i;14137:184::-;14207:6;14260:2;14248:9;14239:7;14235:23;14231:32;14228:52;;;14276:1;14273;14266:12;14228:52;-1:-1:-1;14299:16:1;;14137:184;-1:-1:-1;14137:184:1:o;14326:380::-;14416:4;14474:11;14461:25;14564:66;14553:8;14537:14;14533:29;14529:102;14509:18;14505:127;14495:155;;14646:1;14643;14636:12;14495:155;14667:33;;;;;14326:380;-1:-1:-1;;14326:380:1:o;14711:580::-;14788:4;14794:6;14854:11;14841:25;14944:66;14933:8;14917:14;14913:29;14909:102;14889:18;14885:127;14875:155;;15026:1;15023;15016:12;14875:155;15053:33;;15105:20;;;-1:-1:-1;15148:18:1;15137:30;;15134:50;;;15180:1;15177;15170:12;15134:50;15213:4;15201:17;;-1:-1:-1;15244:14:1;15240:27;;;15230:38;;15227:58;;;15281:1;15278;15271:12;15296:271;15479:6;15471;15466:3;15453:33;15435:3;15505:16;;15530:13;;;15505:16;15296:271;-1:-1:-1;15296:271:1:o;15982:184::-;16034:77;16031:1;16024:88;16131:4;16128:1;16121:15;16155:4;16152:1;16145:15;16171:128;16238:9;;;16259:11;;;16256:37;;;16273:18;;:::i;17171:174::-;17238:12;17270:10;;;17282;;;17266:27;;17305:11;;;17302:37;;;17319:18;;:::i;:::-;17302:37;17171:174;;;;:::o;17757:758::-;17826:5;17874:4;17862:9;17857:3;17853:19;17849:30;17846:50;;;17892:1;17889;17882:12;17846:50;17925:2;17919:9;17967:4;17959:6;17955:17;18038:6;18026:10;18023:22;18002:18;17990:10;17987:34;17984:62;17981:88;;;18049:18;;:::i;:::-;18089:10;18085:2;18078:22;;18118:6;18109:15;;18154:9;18148:16;18195:1;18186:7;18183:14;18173:42;;18211:1;18208;18201:12;18173:42;18224:23;;18292:2;18277:18;;18271:25;18305:32;18271:25;18305:32;:::i;:::-;18365:2;18353:15;;18346:32;18423:2;18408:18;;18402:25;18436:32;18402:25;18436:32;:::i;:::-;18496:2;18484:15;;;;18477:32;17757:758;;-1:-1:-1;;17757:758:1:o;18520:257::-;18619:6;18672:2;18660:9;18651:7;18647:23;18643:32;18640:52;;;18688:1;18685;18678:12;18640:52;18711:60;18763:7;18752:9;18711:60;:::i;19429:386::-;19537:6;19545;19598:3;19586:9;19577:7;19573:23;19569:33;19566:53;;;19615:1;19612;19605:12;19566:53;19647:9;19641:16;19666:31;19691:5;19666:31;:::i;:::-;19716:5;-1:-1:-1;19740:69:1;19801:7;19796:2;19781:18;;19740:69;:::i;:::-;19730:79;;19429:386;;;;;:::o;19820:195::-;19859:3;19890:66;19883:5;19880:77;19877:103;;19960:18;;:::i;:::-;-1:-1:-1;20007:1:1;19996:13;;19820:195::o;20741:175::-;20809:10;20852;;;20840;;;20836:27;;20875:12;;;20872:38;;;20890:18;;:::i;20921:626::-;21165:4;21194:10;21243:2;21235:6;21231:15;21220:9;21213:34;21295:2;21287:6;21283:15;21278:2;21267:9;21263:18;21256:43;21335:6;21330:2;21319:9;21315:18;21308:34;21378:6;21373:2;21362:9;21358:18;21351:34;21434:2;21426:6;21422:15;21416:3;21405:9;21401:19;21394:44;;21475:3;21469;21458:9;21454:19;21447:32;21496:45;21536:3;21525:9;21521:19;21513:6;21496:45;:::i;21820:357::-;21938:12;;21985:4;21974:16;;;21968:23;;21938:12;22003:16;;22000:171;;;22093:66;22077:4;22073:17;;;;22070:1;22066:25;22062:98;22051:110;;21820:357;-1:-1:-1;21820:357:1:o;22182:475::-;22372:4;22401:10;22450:2;22442:6;22438:15;22427:9;22420:34;22502:2;22494:6;22490:15;22485:2;22474:9;22470:18;22463:43;;22542:6;22537:2;22526:9;22522:18;22515:34;22585:3;22580:2;22569:9;22565:18;22558:31;22606:45;22646:3;22635:9;22631:19;22623:6;22606:45;:::i;22662:277::-;22729:6;22782:2;22770:9;22761:7;22757:23;22753:32;22750:52;;;22798:1;22795;22788:12;22750:52;22830:9;22824:16;22883:5;22876:13;22869:21;22862:5;22859:32;22849:60;;22905:1;22902;22895:12;23356:125;23421:9;;;23442:10;;;23439:36;;;23455:18;;:::i;26121:287::-;26250:3;26288:6;26282:13;26304:66;26363:6;26358:3;26351:4;26343:6;26339:17;26304:66;:::i","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"synapseDomain_","type":"uint32"},{"internalType":"address","name":"agentManager_","type":"address"},{"internalType":"address","name":"inbox_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExecuted","type":"error"},{"inputs":[],"name":"AlreadyFailed","type":"error"},{"inputs":[],"name":"CallerNotAgentManager","type":"error"},{"inputs":[],"name":"CallerNotInbox","type":"error"},{"inputs":[],"name":"DisputeTimeoutNotOver","type":"error"},{"inputs":[],"name":"DuplicatedSnapshotRoot","type":"error"},{"inputs":[],"name":"FlagOutOfRange","type":"error"},{"inputs":[],"name":"GasLimitTooLow","type":"error"},{"inputs":[],"name":"GasSuppliedTooLow","type":"error"},{"inputs":[],"name":"IncorrectDestinationDomain","type":"error"},{"inputs":[],"name":"IncorrectMagicValue","type":"error"},{"inputs":[],"name":"IncorrectOriginDomain","type":"error"},{"inputs":[],"name":"IncorrectSnapshotRoot","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"MessageOptimisticPeriod","type":"error"},{"inputs":[],"name":"NotaryInDispute","type":"error"},{"inputs":[],"name":"OccupiedMemory","type":"error"},{"inputs":[],"name":"OutdatedNonce","type":"error"},{"inputs":[],"name":"PrecompileOutOfGas","type":"error"},{"inputs":[],"name":"TreeHeightTooLow","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedAttestation","type":"error"},{"inputs":[],"name":"UnformattedBaseMessage","type":"error"},{"inputs":[],"name":"UnformattedCallData","type":"error"},{"inputs":[],"name":"UnformattedCallDataPrefix","type":"error"},{"inputs":[],"name":"UnformattedMessage","type":"error"},{"inputs":[],"name":"UnformattedReceipt","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"agentRoot","type":"bytes32"}],"name":"AgentRootAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"remoteDomain","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"Executed","type":"event"},{"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":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"paddedTips","type":"uint256"}],"name":"TipsRecorded","type":"event"},{"inputs":[{"internalType":"uint32","name":"notaryIndex","type":"uint32"},{"internalType":"uint256","name":"sigIndex","type":"uint256"},{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes32","name":"agentRoot","type":"bytes32"},{"internalType":"ChainGas[]","name":"snapGas","type":"uint128[]"}],"name":"acceptAttestation","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"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":"attestationsAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"destStatus","outputs":[{"internalType":"uint40","name":"snapRootTime","type":"uint40"},{"internalType":"uint40","name":"agentRootTime","type":"uint40"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"msgPayload","type":"bytes"},{"internalType":"bytes32[]","name":"originProof","type":"bytes32[]"},{"internalType":"bytes32[]","name":"snapProof","type":"bytes32[]"},{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","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":"getAttestation","outputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"snapRoot","type":"bytes32"}],"name":"getAttestationNonce","outputs":[{"internalType":"uint32","name":"attNonce","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"}],"name":"getGasData","outputs":[{"internalType":"GasData","name":"gasData","type":"uint96"},{"internalType":"uint256","name":"dataMaturity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"agentRoot","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"name":"isValidReceipt","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"lastAttestationNonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"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":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageReceipt","outputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageStatus","outputs":[{"internalType":"enum MessageStatus","name":"status","type":"uint8"}],"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":"nextAgentRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"passAgentRoot","outputs":[{"internalType":"bool","name":"rootPending","type":"bool"}],"stateMutability":"nonpayable","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":{"events":{"Executed(uint32,bytes32,bool)":{"notice":"Emitted when message is executed."},"TipsRecorded(bytes32,uint256)":{"notice":"Emitted when message tips are recorded."}},"kind":"user","methods":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":{"notice":"Accepts an attestation, which local `AgentManager` verified to have been signed by an active Notary for this chain. \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain. - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree. - Messages coming from chains included in the Attestation's snapshot could be proven. - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is in Dispute. \u003e - Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local `AgentManager`."},"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."},"attestationsAmount()":{"notice":"Returns the total amount of Notaries attestations that have been accepted."},"destStatus()":{"notice":"Returns status of Destination contract as far as snapshot/agent roots are concerned"},"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"notice":"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"getAttestation(uint256)":{"notice":"Returns a Notary-signed attestation with a given index. \u003e Index refers to the list of all attestations accepted by this contract."},"getAttestationNonce(bytes32)":{"notice":"Returns attestation nonce for a given snapshot root."},"getGasData(uint32)":{"notice":"Returns the gas data for a given chain from the latest accepted attestation with that chain."},"inbox()":{"notice":"Returns the address of the local Inbox contract, which is treated as the \"source of truth\" for agent-signed statements."},"initialize(bytes32)":{"notice":"Initializes Destination contract: - msg.sender is set as contract owner"},"isValidReceipt(bytes)":{"notice":"Checks the validity of the unsigned message receipt."},"lastAttestationNonce(uint32)":{"notice":"Returns the nonce of the last attestation submitted by a Notary with a given agent index."},"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"},"messageReceipt(bytes32)":{"notice":"Returns a formatted payload with the message receipt."},"messageStatus(bytes32)":{"notice":"Returns message execution status: None/Failed/Success."},"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."},"nextAgentRoot()":{"notice":"Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over."},"openDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened."},"passAgentRoot()":{"notice":"Attempts to pass a quarantined Agent Merkle Root to a local Light Manager."},"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":"`Destination` contract is used for receiving messages from other chains. It relies on Notary-signed statements to get the truthful states of the remote chains. These states are then used to verify the validity of the messages sent from the remote chains. `Destination` is responsible for the following: - Accepting the Attestations from the local Inbox contract. - Using these Attestations to execute the messages (see parent `ExecutionHub`). - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,   if deployed on a non-Synapse chain. - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed   by the local `GasOracle` contract.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":{"params":{"agentRoot":"Agent Merkle Root from the Attestation","attPayload":"Raw payload with Attestation data","notaryIndex":"Index of Attestation Notary in Agent Merkle Tree","sigIndex":"Index of stored Notary signature","snapGas":"Gas data for each chain in the Attestation's snapshot"},"returns":{"wasAccepted":"     Whether the Attestation was accepted"}},"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)."}},"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"details":"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.","params":{"gasLimit":"Gas limit for message execution","msgPayload":"Raw payload with a formatted message to execute","originProof":"Proof of inclusion of message in the Origin Merkle Tree","snapProof":"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree","stateIndex":"Index of Origin State in the Snapshot"}},"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)"}},"getAttestation(uint256)":{"details":"Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.","params":{"index":"Attestation index"},"returns":{"attPayload":"      Raw payload with Attestation data","attSignature":"    Notary signature for the reported attestation"}},"getAttestationNonce(bytes32)":{"details":"Will return 0 if the root is unknown."},"getGasData(uint32)":{"details":"Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.","params":{"domain":"Domain for the chain"},"returns":{"dataMaturity":"    Gas data age in seconds","gasData":"         Gas data for the chain"}},"isValidReceipt(bytes)":{"details":"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.","params":{"rcptPayload":"Raw payload with Receipt data"},"returns":{"isValid":"         Whether the requested receipt 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)"}},"messageReceipt(bytes32)":{"details":"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.","params":{"messageHash":"Hash of the message payload"},"returns":{"rcptPayload":"            Formatted payload with the message execution receipt"}},"messageStatus(bytes32)":{"params":{"messageHash":"Hash of the message payload"},"returns":{"status":"          Message execution status"}},"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."},"passAgentRoot()":{"details":"Will do nothing, if root optimistic period is not over.","returns":{"rootPending":" Whether there is a pending agent merkle root left"}},"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":{"_nextAgentRoot":{"details":"Invariant: this is either current LightManager root, or the pending root to be passed to LightManager once its optimistic period is over."},"_storedAttestations":{"details":"Stored lookup data for all accepted Notary Attestations"},"_storedGasData":{"details":"Remote domains GasData submitted by Notaries"},"destStatus":{"returns":{"agentRootTime":"   Timestamp when latest agent root was accepted","notaryIndex":"     Index of Notary who signed the latest agent root","snapRootTime":"    Timestamp when latest snapshot root was accepted"}},"lastAttestationNonce":{"details":"Will return zero if the Notary hasn't submitted any attestations yet."}},"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\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CallerNotAgentManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CallerNotInbox\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputeTimeoutNotOver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicatedSnapshotRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlagOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasSuppliedTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectDestinationDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectMagicValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectOriginDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSnapshotRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageOptimisticPeriod\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotaryInDispute\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OccupiedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutdatedNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrecompileOutOfGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TreeHeightTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedAttestation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedBaseMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedCallData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedCallDataPrefix\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedReceipt\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"}],\"name\":\"AgentRootAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"remoteDomain\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"Executed\",\"type\":\"event\"},{\"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\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"}],\"name\":\"TipsRecorded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"sigIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"},{\"internalType\":\"ChainGas[]\",\"name\":\"snapGas\",\"type\":\"uint128[]\"}],\"name\":\"acceptAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\":\"attestationsAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destStatus\",\"outputs\":[{\"internalType\":\"uint40\",\"name\":\"snapRootTime\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"agentRootTime\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"msgPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"originProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"snapProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"getAttestation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"snapRoot\",\"type\":\"bytes32\"}],\"name\":\"getAttestationNonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"}],\"name\":\"getGasData\",\"outputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"dataMaturity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"name\":\"isValidReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"lastAttestationNonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"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\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageReceipt\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageStatus\",\"outputs\":[{\"internalType\":\"enum MessageStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"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\":\"nextAgentRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"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\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passAgentRoot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"rootPending\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"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\":{\"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])\":{\"params\":{\"agentRoot\":\"Agent Merkle Root from the Attestation\",\"attPayload\":\"Raw payload with Attestation data\",\"notaryIndex\":\"Index of Attestation Notary in Agent Merkle Tree\",\"sigIndex\":\"Index of stored Notary signature\",\"snapGas\":\"Gas data for each chain in the Attestation's snapshot\"},\"returns\":{\"wasAccepted\":\"     Whether the Attestation was accepted\"}},\"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).\"}},\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"details\":\"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\",\"params\":{\"gasLimit\":\"Gas limit for message execution\",\"msgPayload\":\"Raw payload with a formatted message to execute\",\"originProof\":\"Proof of inclusion of message in the Origin Merkle Tree\",\"snapProof\":\"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\",\"stateIndex\":\"Index of Origin State in the Snapshot\"}},\"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)\"}},\"getAttestation(uint256)\":{\"details\":\"Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.\",\"params\":{\"index\":\"Attestation index\"},\"returns\":{\"attPayload\":\"      Raw payload with Attestation data\",\"attSignature\":\"    Notary signature for the reported attestation\"}},\"getAttestationNonce(bytes32)\":{\"details\":\"Will return 0 if the root is unknown.\"},\"getGasData(uint32)\":{\"details\":\"Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.\",\"params\":{\"domain\":\"Domain for the chain\"},\"returns\":{\"dataMaturity\":\"    Gas data age in seconds\",\"gasData\":\"         Gas data for the chain\"}},\"isValidReceipt(bytes)\":{\"details\":\"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.\",\"params\":{\"rcptPayload\":\"Raw payload with Receipt data\"},\"returns\":{\"isValid\":\"         Whether the requested receipt 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)\"}},\"messageReceipt(bytes32)\":{\"details\":\"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\",\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"rcptPayload\":\"            Formatted payload with the message execution receipt\"}},\"messageStatus(bytes32)\":{\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"status\":\"          Message execution status\"}},\"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.\"},\"passAgentRoot()\":{\"details\":\"Will do nothing, if root optimistic period is not over.\",\"returns\":{\"rootPending\":\" Whether there is a pending agent merkle root left\"}},\"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\":{\"_nextAgentRoot\":{\"details\":\"Invariant: this is either current LightManager root, or the pending root to be passed to LightManager once its optimistic period is over.\"},\"_storedAttestations\":{\"details\":\"Stored lookup data for all accepted Notary Attestations\"},\"_storedGasData\":{\"details\":\"Remote domains GasData submitted by Notaries\"},\"destStatus\":{\"returns\":{\"agentRootTime\":\"   Timestamp when latest agent root was accepted\",\"notaryIndex\":\"     Index of Notary who signed the latest agent root\",\"snapRootTime\":\"    Timestamp when latest snapshot root was accepted\"}},\"lastAttestationNonce\":{\"details\":\"Will return zero if the Notary hasn't submitted any attestations yet.\"}},\"version\":1},\"userdoc\":{\"events\":{\"Executed(uint32,bytes32,bool)\":{\"notice\":\"Emitted when message is executed.\"},\"TipsRecorded(bytes32,uint256)\":{\"notice\":\"Emitted when message tips are recorded.\"}},\"kind\":\"user\",\"methods\":{\"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])\":{\"notice\":\"Accepts an attestation, which local `AgentManager` verified to have been signed by an active Notary for this chain. \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain. - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree. - Messages coming from chains included in the Attestation's snapshot could be proven. - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is in Dispute. \u003e - Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local `AgentManager`.\"},\"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.\"},\"attestationsAmount()\":{\"notice\":\"Returns the total amount of Notaries attestations that have been accepted.\"},\"destStatus()\":{\"notice\":\"Returns status of Destination contract as far as snapshot/agent roots are concerned\"},\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"notice\":\"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"getAttestation(uint256)\":{\"notice\":\"Returns a Notary-signed attestation with a given index. \u003e Index refers to the list of all attestations accepted by this contract.\"},\"getAttestationNonce(bytes32)\":{\"notice\":\"Returns attestation nonce for a given snapshot root.\"},\"getGasData(uint32)\":{\"notice\":\"Returns the gas data for a given chain from the latest accepted attestation with that chain.\"},\"inbox()\":{\"notice\":\"Returns the address of the local Inbox contract, which is treated as the \\\"source of truth\\\" for agent-signed statements.\"},\"initialize(bytes32)\":{\"notice\":\"Initializes Destination contract: - msg.sender is set as contract owner\"},\"isValidReceipt(bytes)\":{\"notice\":\"Checks the validity of the unsigned message receipt.\"},\"lastAttestationNonce(uint32)\":{\"notice\":\"Returns the nonce of the last attestation submitted by a Notary with a given agent index.\"},\"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\"},\"messageReceipt(bytes32)\":{\"notice\":\"Returns a formatted payload with the message receipt.\"},\"messageStatus(bytes32)\":{\"notice\":\"Returns message execution status: None/Failed/Success.\"},\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"},\"nextAgentRoot()\":{\"notice\":\"Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.\"},\"passAgentRoot()\":{\"notice\":\"Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\"},\"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\":\"`Destination` contract is used for receiving messages from other chains. It relies on Notary-signed statements to get the truthful states of the remote chains. These states are then used to verify the validity of the messages sent from the remote chains. `Destination` is responsible for the following: - Accepting the Attestations from the local Inbox contract. - Using these Attestations to execute the messages (see parent `ExecutionHub`). - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,   if deployed on a non-Synapse chain. - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed   by the local `GasOracle` contract.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"Destination\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":"39fe2736","acceptOwnership()":"79ba5097","agentManager()":"7622f78d","agentStatus(address)":"28f3fac9","attestationsAmount()":"3cf7b120","destStatus()":"40989152","execute(bytes,bytes32[],bytes32[],uint8,uint64)":"883099bc","getAgent(uint256)":"2de5aaf7","getAttestation(uint256)":"29be4db2","getAttestationNonce(bytes32)":"4f127567","getGasData(uint32)":"d0dd0675","inbox()":"fb0e722b","initialize(bytes32)":"9498bd71","isValidReceipt(bytes)":"e2f006f7","lastAttestationNonce(uint32)":"305b29ee","latestDisputeStatus(uint32)":"dfadd81a","localDomain()":"8d3638f4","messageReceipt(bytes32)":"daa74a9e","messageStatus(bytes32)":"3c6cf473","multicall((bool,bytes)[])":"60fc8466","nextAgentRoot()":"55252dd1","openDispute(uint32,uint32)":"a2155c34","owner()":"8da5cb5b","passAgentRoot()":"a554d1e3","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","resolveDispute(uint32,uint32)":"61169218","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","version()":"54fd4d50"}},"solidity/DestinationHarness.t.sol:DestinationEvents":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"bytes32","name":"agentRoot","type":"bytes32"}],"name":"AgentRootAccepted","type":"event"}],"userDoc":{"kind":"user","methods":{},"notice":"A collection of events emitted by the Destination contract","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"}],\"name\":\"AgentRootAccepted\",\"type\":\"event\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"A collection of events emitted by the Destination contract\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"DestinationEvents\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:DestinationHarness":{"code":"0x6101406040523480156200001257600080fd5b50604051620053b5380380620053b5833981016040819052620000359162000164565b60408051808201909152600580825264302e302e3360d81b60208301526080528390839083908383838383816200006c81620001b8565b60a081815250505062000089620000bc60201b620020171760201c565b63ffffffff90811660c0521660e052506001600160a01b0391821661010052166101205250620001e09650505050505050565b6000620000d446620000d960201b6200201e1760201c565b905090565b600063ffffffff821115620001435760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840160405180910390fd5b5090565b80516001600160a01b03811681146200015f57600080fd5b919050565b6000806000606084860312156200017a57600080fd5b835163ffffffff811681146200018f57600080fd5b92506200019f6020850162000147565b9150620001af6040850162000147565b90509250925092565b80516020808301519190811015620001da576000198160200360031b1b821691505b50919050565b60805160a05160c05160e05161010051610120516150ba620002fb6000396000818161059e0152818161087801528181610935015261316001526000818161043d01528181610cda01528181610ed5015281816117ea0152818161190a01528181611ba201528181611d0d015281816120f3015281816121a90152613042015260008181610416015281816107f201528181610c7f0152818161176401528181611b470152818161269e01526130f50152600081816104970152818161081901528181610ca6015281816110b9015281816111310152818161178b01528181611b6e01528181612675015281816127940152818161311c015281816133ce01526134a20152600061039a0152600061037701526150ba6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80637622f78d11610104578063a554d1e3116100a2578063e2f006f711610071578063e2f006f714610562578063e30c397814610575578063f2fde38b14610586578063fb0e722b1461059957600080fd5b8063a554d1e3146104f0578063d0dd0675146104f8578063daa74a9e1461052f578063dfadd81a1461054257600080fd5b80638d3638f4116100de5780638d3638f4146104925780638da5cb5b146104b95780639498bd71146104ca578063a2155c34146104dd57600080fd5b80637622f78d1461043857806379ba509714610477578063883099bc1461047f57600080fd5b8063409891521161017c57806360fc84661161014b57806360fc8466146103d457806361169218146103f4578063715018a614610409578063717b86381461041157600080fd5b806340989152146102dc5780634f1275671461033c57806354fd4d501461036b57806355252dd1146103cc57600080fd5b8063305b29ee116101b8578063305b29ee1461024a57806339fe2736146102865780633c6cf473146102a95780633cf7b120146102c957600080fd5b806328f3fac9146101df57806329be4db2146102085780632de5aaf714610229575b600080fd5b6101f26101ed366004614676565b6105c0565b6040516101ff91906146f7565b60405180910390f35b61021b610216366004614705565b6105ec565b6040516101ff92919061476e565b61023c610237366004614705565b6108fa565b6040516101ff929190614793565b6102716102583660046147c2565b6101616020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101ff565b6102996102943660046148bd565b610928565b60405190151581526020016101ff565b6102bc6102b7366004614705565b610bcd565b6040516101ff91906149e2565b61012f545b6040519081526020016101ff565b610160546103129064ffffffffff80821691650100000000008104909116906a0100000000000000000000900463ffffffff1683565b6040805164ffffffffff948516815293909216602084015263ffffffff16908201526060016101ff565b61027161034a366004614705565b60009081526101306020526040902054640100000000900463ffffffff1690565b604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516101ff91906149f5565b6102ce610c7b565b6103e76103e2366004614a54565b610d5f565b6040516101ff9190614a96565b610407610402366004614b2a565b610eca565b005b610407610fe6565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ff565b610407610ff0565b61040761048d366004614b63565b611083565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b6033546001600160a01b031661045f565b6104076104d8366004614705565b611648565b6104076104eb366004614b2a565b6118ff565b610299611b43565b61050b6105063660046147c2565b611d7b565b604080516bffffffffffffffffffffffff90931683526020830191909152016101ff565b6103bf61053d366004614705565b611e48565b6105556105503660046147c2565b611ee7565b6040516101ff9190614c2c565b610299610570366004614c67565b611f7b565b6065546001600160a01b031661045f565b610407610594366004614676565b611f8e565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b60408051606081018252600080825260208201819052918101919091526105e68261209e565b92915050565b61012f546060908190831061062d576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061012f848154811061064357610643614c9c565b600091825260208083209091015480835261013082526040808420815160e081018352815463ffffffff8082168352640100000000820481169683019690965264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909516608082015276010000000000000000000000000000000000000000000090940490911660a08401526001015460c08301526101628054919450919291908790811061071c5761071c614c9c565b90600052602060002090600202016040518060400160405290816000820154815260200160018201548152505090506107ee8382602001518460200151856040015186606001516040805160208101969096528581019490945260e09290921b7fffffffff0000000000000000000000000000000000000000000000000000000016606085015260d890811b7fffffffffff000000000000000000000000000000000000000000000000000000908116606486015291901b1660698301528051604e818403018152606e909201905290565b94507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146108f25760c08201516040517fddeffa6600000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ddeffa6690602401600060405180830381865afa1580156108c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108ef9190810190614ccb565b93505b505050915091565b6040805160608101825260008082526020820181905291810182905261091f8361215e565b91509150915091565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461098c576040517fdbc2fa8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109958661221c565b156109cc576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109d586612251565b15610a0c576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a1785612328565b90506000610a248261233b565b63ffffffff808a166000908152610161602052604090205491925090811690821611610a7c576040517f7b7fd2c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88811660009081526101616020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016918316919091179055610acb82898961234d565b6101626040518060400160405280878152602001610ae8856125f0565b905281546001818101845560009384526020808520845160029094020192835590920151910155610b17611b43565b9050610b2481878b612601565b80516101608054602084015160409094015163ffffffff166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff64ffffffffff95861665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000090931695909416949094171791909116919091179055610bbc858a61274a565b600193505050505b95945050505050565b600081815261012d602090815260408083208151608081018352905463ffffffff80821683526401000000008204169382019390935268010000000000000000830460ff169181019190915269010000000000000000009091046001600160a01b03166060820181905215610c455750600292915050565b600083815261012e60205260409020546001600160a01b031615610c6c5750600192915050565b50600092915050565b50919050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1614610cd8575061015f5490565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5a9190614d39565b905090565b6060818067ffffffffffffffff811115610d7b57610d7b6147df565b604051908082528060200260200182016040528015610dc157816020015b604080518082019091526000815260606020820152815260200190600190039081610d995790505b5091503660005b82811015610ec157858582818110610de257610de2614c9c565b9050602002810190610df49190614d52565b91506000848281518110610e0a57610e0a614c9c565b60200260200101519050306001600160a01b0316838060200190610e2e9190614d90565b604051610e3c929190614df5565b600060405180830381855af49150503d8060008114610e77576040519150601f19603f3d011682016040523d82523d6000602084013e610e7c565b606091505b5060208301521515808252833517610eb8577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610dc8565b50505092915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f2c576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f36612967565b63ffffffff848116600090815260c960205260409020805464ffffffffff84166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff00909116176002179055909150821615610fe15763ffffffff8216600090815260c96020526040902080547fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff0016660100000000000064ffffffffff8416021790555b505050565b610fee612972565b565b60655433906001600160a01b031681146110775760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b611080816129cc565b50565b61108b6129fd565b600061109688612a56565b905060006110a382612a69565b905060006110b083612a7f565b905063ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602083901c6cffffffffffffffffffffffffff1663ffffffff161461112a576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016606083901c64ffffffffff1663ffffffff160361119a576040517f3eeb1dd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815261012d60209081526040918290208251608081018452905463ffffffff80821683526401000000008204169282019290925268010000000000000000820460ff1692810192909252690100000000000000000090046001600160a01b0316606082018190521561123b576040517f0dc1019700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061124c84848d8d8d8d8d612b3f565b905060008160a0015164ffffffffff16426112679190614e34565b905063ffffffff85168110156112a9576040517f5e5728e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080806112c98870ffffffffffffffffffffffffffffffffff16612db1565b60018111156112da576112da614693565b036113135760006112f26112ed8a612de4565b612df0565b905061130088858c84612e31565b915061130b81612fd1565b925050611329565b61132687846113218b612de4565b612fe2565b90505b845163ffffffff1660000361147e5763ffffffff606088901c81168652608085015116602086015260ff8a166040860152801561136b573360608601526113a3565b600086815261012e6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b600086815261012d602090815260409182902087518154928901519389015160608a01516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9092166801000000000000000002919091167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff968716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009096169690931695909517939093171692909217179055611597565b806114b5576040517f589a41b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360608601908152600087815261012d602090815260409182902088518154928a0151938a015194516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9096166801000000000000000002959095167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090951695909216949094179290921791909116919091179190911790555b6040518115158152869063ffffffff60608a901c16907f39c48fd1b2185b07007abc7904a8cdf782cfe449fd0e9bba1c2223a691e15f0b9060200160405180910390a36115ef846000015185602001518885896130f1565b61162d5760408051878152602081018490527f22bd0cccf7173839e6f30c797b419921d48a23b0732d0b120c600a49247d3016910160405180910390a15b505050505050505061163f600160fb55565b50505050505050565b600054610100900460ff16158080156116685750600054600160ff909116105b806116825750303b158015611682575060005460ff166001145b6116f45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161106e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561175257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61175a61320d565b611762613292565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146118985761015f8290556040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b15801561183657600080fd5b505af115801561184a573d6000803e3d6000fd5b50505050611856612967565b610160805464ffffffffff9290921665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff9092169190911790555b80156118fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611961576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061196b612967565b9050600060405180606001604052806001600281111561198d5761198d614693565b815264ffffffffff84166020808301919091526000604092830181905263ffffffff8816815260c99091522081518154929350839282907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156119fa576119fa614693565b0217905550602082810151825460409485015164ffffffffff9081166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff9190931661010002167fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff909116171790915563ffffffff8516600090815260c990915220815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115611ac457611ac4614693565b0217905550602082015181546040909301517fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff90931661010064ffffffffff928316027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff16176601000000000000919093160291909117905550505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1603611b9e5750600090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c229190614d39565b61015f54909150808203611c395760009250505090565b604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff1691810182905290611c859061221c565b15611c9657505061015f5550600090565b611ca38160400151612251565b15611cb2576001935050505090565b60208101514290611cc7906201518090614e47565b64ffffffffff161115611cde576001935050505090565b6040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b158015611d5957600080fd5b505af1158015611d6d573d6000803e3d6000fd5b505050506000935050505090565b63ffffffff818116600090815261016360209081526040808320815160608101835290546bffffffffffffffffffffffff811682526c0100000000000000000000000081049095169281019290925270010000000000000000000000000000000090930464ffffffffff16928101839052909182919015801590611e095750611e07816020015161221c565b155b8015611e1f5750611e1d8160200151612251565b155b15611e425780516040820151909350611e3f9064ffffffffff1642614e34565b91505b50915091565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b03166060808301919091529290919003611ed6575050604080516020810190915260008152919050565b611ee08382613317565b9392505050565b604080516060810182526000808252602082018190529181019190915263ffffffff8216600090815260c96020526040908190208151606081019092528054829060ff166002811115611f3c57611f3c614693565b6002811115611f4d57611f4d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015292915050565b60006105e6611f898361348b565b61349e565b611f96612972565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611fdf6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610d5a465b600063ffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f3220626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b5090565b60408051606081018252600080825260208201819052918101919091526040517f28f3fac90000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000016906328f3fac990602401606060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e69190614ee8565b604080516060810182526000808252602082018190529181018290526040517f2de5aaf7000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632de5aaf790602401608060405180830381865afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190614f04565b60008063ffffffff8316600090815260c9602052604090205460ff16600281111561224957612249614693565b141592915050565b63ffffffff8116600090815260c96020526040808220815160608101909252805483929190829060ff16600281111561228c5761228c614693565b600281111561229d5761229d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015290506000815160028111156122dc576122dc614693565b146122ea5750600092915050565b806020015164ffffffffff166000036123065750600092915050565b60408101516123189061a8c090614e47565b64ffffffffff1642109392505050565b60006105e661233683613749565b61375c565b60006105e660406004845b919061379d565b6000612358846137be565b60008181526101306020526040902054909150760100000000000000000000000000000000000000000000900464ffffffffff16156123c3576040517fa789712900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808463ffffffff1681526020016123e38661233b565b63ffffffff1681526020016123f7866137cc565b64ffffffffff16815260200161240c866137db565b64ffffffffff16815260200161242761012f8054905061201e565b63ffffffff16815260200161243a612967565b64ffffffffff90811682526020918201949094526000838152610130825260408082208451815494860151928601516060870151608088015160a08901518b16760100000000000000000000000000000000000000000000027fffffffffff0000000000ffffffffffffffffffffffffffffffffffffffffffff63ffffffff928316720100000000000000000000000000000000000002167fffffffffff000000000000000000ffffffffffffffffffffffffffffffffffff938d166d0100000000000000000000000000027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff95909d166801000000000000000002949094167fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff978316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909a16929095169190911797909717949094169190911797909717919091169590951791909117845560c09091015160019384015561012f8054938401815590527f232da9e50dad2971456a78fb5cd6ff6b75019984d6e918139ce990999420f979909101555050565b60006105e6602080845b91906137ea565b604080516060810182526000808252602082018190529181019190915250604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff169181019190915261266a612967565b64ffffffffff1681527f000000000000000000000000000000000000000000000000000000000000000063ffffffff9081167f000000000000000000000000000000000000000000000000000000000000000091909116148015906126cd575083155b80156126dc57508261015f5414155b15611ee0576126e9612967565b64ffffffffff16602082015263ffffffff821660408083019190915261015f849055517fc8ba82607c756c8ae67c7e47c27ade0b0718d492495044a1f8619663f26ebaa39061273b9085815260200190565b60405180910390a19392505050565b815160005b8181101561296157600084828151811061276b5761276b614c9c565b602002602001015190506000612790826fffffffffffffffffffffffffffffffff1690565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff16036127cc57505061294f565b63ffffffff81811660009081526101636020908152604091829020825160608101845290546bffffffffffffffffffffffff8082168084526c0100000000000000000000000083049096168385015270010000000000000000000000000000000090910464ffffffffff1693820193909352929085901c909116908103612856575050505061294f565b6040518060600160405280826bffffffffffffffffffffffff1681526020018863ffffffff168152602001612889612967565b64ffffffffff90811690915263ffffffff9485166000908152610163602090815260409182902084518154928601519590930151909316700100000000000000000000000000000000027fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff949097166c01000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009091166bffffffffffffffffffffffff909216919091171791909116939093179092555050505b8061295981614f3a565b91505061274f565b50505050565b6000610d5a426138f4565b6033546001600160a01b03163314610fee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161106e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561108081613971565b600260fb5403612a4f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161106e565b600260fb55565b60006105e6612a6483613749565b6139db565b60006105e6612a7a82601185612346565b613a1c565b600080612a8b83612a69565b90506000612aab8270ffffffffffffffffffffffffffffffffff16612db1565b6001811115612abc57612abc614693565b03612b0057611ee0612ae78270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612af66112ed87612de4565b613a60565b613a86565b611ee0612b268270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612b3a612b3587612de4565b613ad2565b613b13565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526000612bdc600160408b901c68ffffffffffffffffff16612b999190614f72565b63ffffffff168989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060209250613b23915050565b90506000612c2b8260608c901c64ffffffffff168888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250613bcb915050565b600081815261013060209081526040808320815160e081018352815463ffffffff8082168352640100000000820481169583019590955264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909416608082015276010000000000000000000000000000000000000000000090930490911660a0830181905260019091015460c083015290955091925003612d20576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d2b9061221c565b15612d62576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d6d90612251565b15612da4576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050979650505050505050565b6000612dd08270ffffffffffffffffffffffffffffffffff1660801c90565b60ff1660018111156105e6576105e6614693565b600081611ee081613c2b565b6000612dfb82613c42565b61209a576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080612e3d83613c77565b905067ffffffffffffffff602082901c81169085161015612e8a576040517fed43c3a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612e9b612e9885613c93565b90565b90508467ffffffffffffffff165a11612ee0576040517faa6c898500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000606088901c64ffffffffff16604089901c68ffffffffffffffffff16612f07876125f0565b8977ffffffffffffffffffffffffffffffffffffffffffffffff8716612f34612f2f8b613ca2565b613cc5565b604051602401612f4996959493929190614f8f565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f032f287e000000000000000000000000000000000000000000000000000000001790529050612fc36001600160a01b03831667ffffffffffffffff8816600084613d04565b93505050505b949350505050565b60006105e6612e9882602085612346565b600080612fee83613ad2565b90506000613031606087901c64ffffffffff166040805163ffffffff9092166020830152810187905260600160408051601f198184030181529190528390613d36565b905060006130686001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683613e64565b9050805160201415806130ad575061307f83613ea8565b7fffffffff00000000000000000000000000000000000000000000000000000000166130aa82614fcc565b14155b156130e4576040517ff8b4221800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff161461314e57506000610bc4565b8260000361315e57506000610bc4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636b47b3bc87878661319a8988613317565b6040518563ffffffff1660e01b81526004016131b9949392919061500e565b6020604051808303816000875af11580156131d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fc919061503d565b9695505050505050565b600160fb55565b600054610100900460ff1661328a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613eb7565b600054610100900460ff1661330f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613f3d565b600082815261012e60205260409020546060906001600160a01b03168061333f575060608201515b600061012f846020015163ffffffff168154811061335f5761335f614c9c565b6000918252602080832090910154808352610130909152604082205490925061338d9063ffffffff1661215e565b5085516040808801516060808a0151835160e095861b7fffffffff0000000000000000000000000000000000000000000000000000000090811660208301527f000000000000000000000000000000000000000000000000000000000000000090961b9095166024860152602885018c90526048850188905260f89290921b7fff0000000000000000000000000000000000000000000000000000000000000016606885015284811b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116606986015288821b8116607d86015291901b1660918301528051608581840301815260a590920190529091506131fc565b60006105e661349983613749565b613fba565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff166134d083613ffb565b63ffffffff161461350d576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061351883614009565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b031660608201529293509003613596575060009392505050565b805163ffffffff166135a785614018565b63ffffffff161415806135cc5750806040015160ff166135c685614026565b60ff1614155b156135db575060009392505050565b60006135e685614035565b60008181526101306020526040812054919250906136099063ffffffff1661215e565b50905061012f836020015163ffffffff168154811061362a5761362a614c9c565b90600052602060002001548214158061365d5750806001600160a01b031661365187614044565b6001600160a01b031614155b1561366e5750600095945050505050565b600084815261012e60205260409020546001600160a01b0316806136e15783606001516001600160a01b03166136a388614053565b6001600160a01b03161480156136d6575083606001516001600160a01b03166136cb88614060565b6001600160a01b0316145b979650505050505050565b60006136ec88614060565b9050816001600160a01b031661370189614053565b6001600160a01b031614801561373d57506001600160a01b038116158061373d575084606001516001600160a01b0316816001600160a01b0316145b98975050505050505050565b805160009060208301612fc9818361406d565b6000613767826140d0565b61209a576040517feb92662c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806137ab8585856137ea565b602084900360031b1c9150509392505050565b60006105e6816020846125fa565b60006105e66044600584612346565b60006105e66049600584612346565b6000816000036137fc57506000611ee0565b6020821115613837576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416613854838561505f565b111561388c576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b600061389d8660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b600064ffffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201527f3020626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006139e6826140ef565b61209a576040517fd082b2a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600160ff608084901c16111561209a576040517f58ebbfbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6613a7d613a7184612fd1565b60009081526020902090565b612afb846141a4565b600082158015613a94575081155b15613aa1575060006105e6565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506105e6565b6000613add826141b4565b61209a576040517f9d46362800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6826141f0565b6141f0565b815160009082811115613b62576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84915060005b81811015613b9f57613b9583868381518110613b8657613b86614c9c565b6020026020010151898461421b565b9250600101613b68565b50805b83811015613bc157613bb7836000898461421b565b9250600101613ba2565b5050949350505050565b60006101fe600183901b1660408110613c10576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613c1c8787614244565b90506136d68282876006613b23565b60006105e6613c3b60118361505f565b83906142a5565b60006018613c526020604061505f565b613c5c919061505f565b6fffffffffffffffffffffffffffffffff8316101592915050565b60006105e6612e98613c8b6020604061505f565b601885612346565b60006105e660406020846125fa565b60006105e66018613cb56020604061505f565b613c3b919061505f565b906142a5565b60405180613cd6836020830161430b565b506fffffffffffffffffffffffffffffffff83166000601f8201601f19168301602001604052509052919050565b6000846001600160a01b03163b600003613d2057506000612fc9565b600080835160208501868989f195945050505050565b6060613d448251601f161590565b613d7a576040517fd49e9d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160038082526080820190925260009160208201606080368337019050509050613dec613da985613ea8565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091166020820152602401604051602081830303815290604052613749565b81600081518110613dff57613dff614c9c565b602002602001018181525050613e1483613749565b81600181518110613e2757613e27614c9c565b602002602001018181525050613e3c846143b4565b81600281518110613e4f57613e4f614c9c565b602002602001018181525050612fc9816143c2565b6060611ee0838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250614400565b600081611ee0818360046137ea565b600054610100900460ff16613f345760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee336129cc565b600054610100900460ff166132065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b6000613fc5826144e7565b61209a576040517f76b4e13c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e660048084612346565b60006105e660086020846125fa565b60006105e681600484612346565b60006105e66048600184612346565b60006105e660286020846125fa565b60006105e66049835b90614503565b60006105e6605d8361404d565b60006105e660718361404d565b60008061407a838561505f565b905060405181111561408a575060005b806000036140c4576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317612fc9565b6000604e6fffffffffffffffffffffffffffffffff83165b1492915050565b60006fffffffffffffffffffffffffffffffff821661410f60118361505f565b81101561411f5750600092915050565b600061412a84614511565b9050600160ff608083901c161115614146575060009392505050565b600061416c61415483613a1c565b70ffffffffffffffffffffffffffffffffff16612db1565b600181111561417d5761417d614693565b0361419357612fc961418e85613c2b565b613c42565b612fc961419f85613c2b565b6141b4565b60006105e6613b1e602084613cbf565b60006fffffffffffffffffffffffffffffffff821660048110156141db5750600092915050565b611ee06141e9600483614e34565b601f161590565b6000806141fd8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b6000600183831c16810361423a576142338585613a86565b9050612fc9565b6142338486613a86565b6000828260405160200161428792919091825260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015260240190565b60405160208183030381529060405280519060200120905092915050565b60006fffffffffffffffffffffffffffffffff8316808311156142f4576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fc9836143028660801c90565b0184830361406d565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c9080851015614365576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa9050806143a8576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b84176136d6565b600081611ee08160046142a5565b6040518060006143d5846020840161451f565b6fffffffffffffffffffffffffffffffff16601f8101601f1916830160200160405290915250919050565b6060824710156144785760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161106e565b600080866001600160a01b031685876040516144949190615072565b60006040518083038185875af1925050503d80600081146144d1576040519150601f19603f3d011682016040523d82523d6000602084013e6144d6565b606091505b50915091506136d6878383876145c3565b600060856fffffffffffffffffffffffffffffffff83166140e8565b6000611ee08383601461379d565b60006105e68282601161379d565b6040516000908083101561455f576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b85518110156145b657600086828151811061458057614580614c9c565b602002602001015190506145968184880161430b565b506fffffffffffffffffffffffffffffffff169190910190600101614563565b50608084901b8117610bc4565b6060831561463257825160000361462b576001600160a01b0385163b61462b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161106e565b5081612fc9565b612fc983838151156146475781518083602001fd5b8060405162461bcd60e51b815260040161106e91906149f5565b6001600160a01b038116811461108057600080fd5b60006020828403121561468857600080fd5b8135611ee081614661565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051600681106146d4576146d4614693565b825260208181015163ffffffff9081169184019190915260409182015116910152565b606081016105e682846146c2565b60006020828403121561471757600080fd5b5035919050565b60005b83811015614739578181015183820152602001614721565b50506000910152565b6000815180845261475a81602086016020860161471e565b601f01601f19169290920160200192915050565b6040815260006147816040830185614742565b8281036020840152610bc48185614742565b6001600160a01b038316815260808101611ee060208301846146c2565b63ffffffff8116811461108057600080fd5b6000602082840312156147d457600080fd5b8135611ee0816147b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614837576148376147df565b604052919050565b600067ffffffffffffffff821115614859576148596147df565b50601f01601f191660200190565b600082601f83011261487857600080fd5b813561488b6148868261483f565b61480e565b8181528460208386010111156148a057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156148d557600080fd5b85356148e0816147b0565b94506020868101359450604087013567ffffffffffffffff8082111561490557600080fd5b6149118a838b01614867565b955060608901359450608089013591508082111561492e57600080fd5b818901915089601f83011261494257600080fd5b813581811115614954576149546147df565b8060051b915061496584830161480e565b818152918301840191848101908c84111561497f57600080fd5b938501935b838510156149bf57843592506fffffffffffffffffffffffffffffffff831683146149af5760008081fd5b8282529385019390850190614984565b8096505050505050509295509295909350565b6003811061108057611080614693565b602081016149ef836149d2565b91905290565b602081526000611ee06020830184614742565b60008083601f840112614a1a57600080fd5b50813567ffffffffffffffff811115614a3257600080fd5b6020830191508360208260051b8501011115614a4d57600080fd5b9250929050565b60008060208385031215614a6757600080fd5b823567ffffffffffffffff811115614a7e57600080fd5b614a8a85828601614a08565b90969095509350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015614b1c578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805115158452870151878401879052614b0987850182614742565b9588019593505090860190600101614abd565b509098975050505050505050565b60008060408385031215614b3d57600080fd5b8235614b48816147b0565b91506020830135614b58816147b0565b809150509250929050565b600080600080600080600060a0888a031215614b7e57600080fd5b873567ffffffffffffffff80821115614b9657600080fd5b614ba28b838c01614867565b985060208a0135915080821115614bb857600080fd5b614bc48b838c01614a08565b909850965060408a0135915080821115614bdd57600080fd5b614be98b838c01614a08565b909650945060608a0135915060ff82168214614c0457600080fd5b9092506080890135908082168214614c1b57600080fd5b508091505092959891949750929550565b81516060820190614c3c816149d2565b80835250602083015164ffffffffff8082166020850152806040860151166040850152505092915050565b600060208284031215614c7957600080fd5b813567ffffffffffffffff811115614c9057600080fd5b612fc984828501614867565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215614cdd57600080fd5b815167ffffffffffffffff811115614cf457600080fd5b8201601f81018413614d0557600080fd5b8051614d136148868261483f565b818152856020838501011115614d2857600080fd5b610bc482602083016020860161471e565b600060208284031215614d4b57600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614d8657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614dc557600080fd5b83018035915067ffffffffffffffff821115614de057600080fd5b602001915036819003821315614a4d57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105e6576105e6614e05565b64ffffffffff818116838216019080821115614e6557614e65614e05565b5092915050565b600060608284031215614e7e57600080fd5b6040516060810181811067ffffffffffffffff82111715614ea157614ea16147df565b8060405250809150825160068110614eb857600080fd5b81526020830151614ec8816147b0565b60208201526040830151614edb816147b0565b6040919091015292915050565b600060608284031215614efa57600080fd5b611ee08383614e6c565b60008060808385031215614f1757600080fd5b8251614f2281614661565b9150614f318460208501614e6c565b90509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f6b57614f6b614e05565b5060010190565b63ffffffff828116828216039080821115614e6557614e65614e05565b600063ffffffff8089168352808816602084015286604084015285606084015280851660808401525060c060a083015261373d60c0830184614742565b80516020808301519190811015610c75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600063ffffffff8087168352808616602084015250836040830152608060608301526131fc6080830184614742565b60006020828403121561504f57600080fd5b81518015158114611ee057600080fd5b808201808211156105e6576105e6614e05565b60008251614d8681846020870161471e56fea2646970667358221220a616f11f6c8333fe4015a6de25a4be94acb62d7e000bb8d6e82c4ae8429713c664736f6c63430008110033","runtime-code":"0x608060405234801561001057600080fd5b50600436106101da5760003560e01c80637622f78d11610104578063a554d1e3116100a2578063e2f006f711610071578063e2f006f714610562578063e30c397814610575578063f2fde38b14610586578063fb0e722b1461059957600080fd5b8063a554d1e3146104f0578063d0dd0675146104f8578063daa74a9e1461052f578063dfadd81a1461054257600080fd5b80638d3638f4116100de5780638d3638f4146104925780638da5cb5b146104b95780639498bd71146104ca578063a2155c34146104dd57600080fd5b80637622f78d1461043857806379ba509714610477578063883099bc1461047f57600080fd5b8063409891521161017c57806360fc84661161014b57806360fc8466146103d457806361169218146103f4578063715018a614610409578063717b86381461041157600080fd5b806340989152146102dc5780634f1275671461033c57806354fd4d501461036b57806355252dd1146103cc57600080fd5b8063305b29ee116101b8578063305b29ee1461024a57806339fe2736146102865780633c6cf473146102a95780633cf7b120146102c957600080fd5b806328f3fac9146101df57806329be4db2146102085780632de5aaf714610229575b600080fd5b6101f26101ed366004614676565b6105c0565b6040516101ff91906146f7565b60405180910390f35b61021b610216366004614705565b6105ec565b6040516101ff92919061476e565b61023c610237366004614705565b6108fa565b6040516101ff929190614793565b6102716102583660046147c2565b6101616020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101ff565b6102996102943660046148bd565b610928565b60405190151581526020016101ff565b6102bc6102b7366004614705565b610bcd565b6040516101ff91906149e2565b61012f545b6040519081526020016101ff565b610160546103129064ffffffffff80821691650100000000008104909116906a0100000000000000000000900463ffffffff1683565b6040805164ffffffffff948516815293909216602084015263ffffffff16908201526060016101ff565b61027161034a366004614705565b60009081526101306020526040902054640100000000900463ffffffff1690565b604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516101ff91906149f5565b6102ce610c7b565b6103e76103e2366004614a54565b610d5f565b6040516101ff9190614a96565b610407610402366004614b2a565b610eca565b005b610407610fe6565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ff565b610407610ff0565b61040761048d366004614b63565b611083565b6102717f000000000000000000000000000000000000000000000000000000000000000081565b6033546001600160a01b031661045f565b6104076104d8366004614705565b611648565b6104076104eb366004614b2a565b6118ff565b610299611b43565b61050b6105063660046147c2565b611d7b565b604080516bffffffffffffffffffffffff90931683526020830191909152016101ff565b6103bf61053d366004614705565b611e48565b6105556105503660046147c2565b611ee7565b6040516101ff9190614c2c565b610299610570366004614c67565b611f7b565b6065546001600160a01b031661045f565b610407610594366004614676565b611f8e565b61045f7f000000000000000000000000000000000000000000000000000000000000000081565b60408051606081018252600080825260208201819052918101919091526105e68261209e565b92915050565b61012f546060908190831061062d576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061012f848154811061064357610643614c9c565b600091825260208083209091015480835261013082526040808420815160e081018352815463ffffffff8082168352640100000000820481169683019690965264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909516608082015276010000000000000000000000000000000000000000000090940490911660a08401526001015460c08301526101628054919450919291908790811061071c5761071c614c9c565b90600052602060002090600202016040518060400160405290816000820154815260200160018201548152505090506107ee8382602001518460200151856040015186606001516040805160208101969096528581019490945260e09290921b7fffffffff0000000000000000000000000000000000000000000000000000000016606085015260d890811b7fffffffffff000000000000000000000000000000000000000000000000000000908116606486015291901b1660698301528051604e818403018152606e909201905290565b94507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146108f25760c08201516040517fddeffa6600000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ddeffa6690602401600060405180830381865afa1580156108c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108ef9190810190614ccb565b93505b505050915091565b6040805160608101825260008082526020820181905291810182905261091f8361215e565b91509150915091565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461098c576040517fdbc2fa8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109958661221c565b156109cc576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109d586612251565b15610a0c576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a1785612328565b90506000610a248261233b565b63ffffffff808a166000908152610161602052604090205491925090811690821611610a7c576040517f7b7fd2c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88811660009081526101616020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016918316919091179055610acb82898961234d565b6101626040518060400160405280878152602001610ae8856125f0565b905281546001818101845560009384526020808520845160029094020192835590920151910155610b17611b43565b9050610b2481878b612601565b80516101608054602084015160409094015163ffffffff166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff64ffffffffff95861665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000090931695909416949094171791909116919091179055610bbc858a61274a565b600193505050505b95945050505050565b600081815261012d602090815260408083208151608081018352905463ffffffff80821683526401000000008204169382019390935268010000000000000000830460ff169181019190915269010000000000000000009091046001600160a01b03166060820181905215610c455750600292915050565b600083815261012e60205260409020546001600160a01b031615610c6c5750600192915050565b50600092915050565b50919050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1614610cd8575061015f5490565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5a9190614d39565b905090565b6060818067ffffffffffffffff811115610d7b57610d7b6147df565b604051908082528060200260200182016040528015610dc157816020015b604080518082019091526000815260606020820152815260200190600190039081610d995790505b5091503660005b82811015610ec157858582818110610de257610de2614c9c565b9050602002810190610df49190614d52565b91506000848281518110610e0a57610e0a614c9c565b60200260200101519050306001600160a01b0316838060200190610e2e9190614d90565b604051610e3c929190614df5565b600060405180830381855af49150503d8060008114610e77576040519150601f19603f3d011682016040523d82523d6000602084013e610e7c565b606091505b5060208301521515808252833517610eb8577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610dc8565b50505092915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f2c576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f36612967565b63ffffffff848116600090815260c960205260409020805464ffffffffff84166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff00909116176002179055909150821615610fe15763ffffffff8216600090815260c96020526040902080547fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff0016660100000000000064ffffffffff8416021790555b505050565b610fee612972565b565b60655433906001600160a01b031681146110775760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b611080816129cc565b50565b61108b6129fd565b600061109688612a56565b905060006110a382612a69565b905060006110b083612a7f565b905063ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602083901c6cffffffffffffffffffffffffff1663ffffffff161461112a576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016606083901c64ffffffffff1663ffffffff160361119a576040517f3eeb1dd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815261012d60209081526040918290208251608081018452905463ffffffff80821683526401000000008204169282019290925268010000000000000000820460ff1692810192909252690100000000000000000090046001600160a01b0316606082018190521561123b576040517f0dc1019700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061124c84848d8d8d8d8d612b3f565b905060008160a0015164ffffffffff16426112679190614e34565b905063ffffffff85168110156112a9576040517f5e5728e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080806112c98870ffffffffffffffffffffffffffffffffff16612db1565b60018111156112da576112da614693565b036113135760006112f26112ed8a612de4565b612df0565b905061130088858c84612e31565b915061130b81612fd1565b925050611329565b61132687846113218b612de4565b612fe2565b90505b845163ffffffff1660000361147e5763ffffffff606088901c81168652608085015116602086015260ff8a166040860152801561136b573360608601526113a3565b600086815261012e6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b600086815261012d602090815260409182902087518154928901519389015160608a01516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9092166801000000000000000002919091167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff968716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009096169690931695909517939093171692909217179055611597565b806114b5576040517f589a41b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360608601908152600087815261012d602090815260409182902088518154928a0151938a015194516001600160a01b03166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff60ff9096166801000000000000000002959095167fffffff000000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090951695909216949094179290921791909116919091179190911790555b6040518115158152869063ffffffff60608a901c16907f39c48fd1b2185b07007abc7904a8cdf782cfe449fd0e9bba1c2223a691e15f0b9060200160405180910390a36115ef846000015185602001518885896130f1565b61162d5760408051878152602081018490527f22bd0cccf7173839e6f30c797b419921d48a23b0732d0b120c600a49247d3016910160405180910390a15b505050505050505061163f600160fb55565b50505050505050565b600054610100900460ff16158080156116685750600054600160ff909116105b806116825750303b158015611682575060005460ff166001145b6116f45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161106e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561175257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61175a61320d565b611762613292565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16146118985761015f8290556040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b15801561183657600080fd5b505af115801561184a573d6000803e3d6000fd5b50505050611856612967565b610160805464ffffffffff9290921665010000000000027fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff9092169190911790555b80156118fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611961576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061196b612967565b9050600060405180606001604052806001600281111561198d5761198d614693565b815264ffffffffff84166020808301919091526000604092830181905263ffffffff8816815260c99091522081518154929350839282907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156119fa576119fa614693565b0217905550602082810151825460409485015164ffffffffff9081166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff9190931661010002167fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff909116171790915563ffffffff8516600090815260c990915220815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115611ac457611ac4614693565b0217905550602082015181546040909301517fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff90931661010064ffffffffff928316027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff16176601000000000000919093160291909117905550505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1603611b9e5750600090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c229190614d39565b61015f54909150808203611c395760009250505090565b604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff1691810182905290611c859061221c565b15611c9657505061015f5550600090565b611ca38160400151612251565b15611cb2576001935050505090565b60208101514290611cc7906201518090614e47565b64ffffffffff161115611cde576001935050505090565b6040517f58668176000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635866817690602401600060405180830381600087803b158015611d5957600080fd5b505af1158015611d6d573d6000803e3d6000fd5b505050506000935050505090565b63ffffffff818116600090815261016360209081526040808320815160608101835290546bffffffffffffffffffffffff811682526c0100000000000000000000000081049095169281019290925270010000000000000000000000000000000090930464ffffffffff16928101839052909182919015801590611e095750611e07816020015161221c565b155b8015611e1f5750611e1d8160200151612251565b155b15611e425780516040820151909350611e3f9064ffffffffff1642614e34565b91505b50915091565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b03166060808301919091529290919003611ed6575050604080516020810190915260008152919050565b611ee08382613317565b9392505050565b604080516060810182526000808252602082018190529181019190915263ffffffff8216600090815260c96020526040908190208151606081019092528054829060ff166002811115611f3c57611f3c614693565b6002811115611f4d57611f4d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015292915050565b60006105e6611f898361348b565b61349e565b611f96612972565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611fdf6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610d5a465b600063ffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f3220626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b5090565b60408051606081018252600080825260208201819052918101919091526040517f28f3fac90000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000016906328f3fac990602401606060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e69190614ee8565b604080516060810182526000808252602082018190529181018290526040517f2de5aaf7000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632de5aaf790602401608060405180830381865afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190614f04565b60008063ffffffff8316600090815260c9602052604090205460ff16600281111561224957612249614693565b141592915050565b63ffffffff8116600090815260c96020526040808220815160608101909252805483929190829060ff16600281111561228c5761228c614693565b600281111561229d5761229d614693565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015290506000815160028111156122dc576122dc614693565b146122ea5750600092915050565b806020015164ffffffffff166000036123065750600092915050565b60408101516123189061a8c090614e47565b64ffffffffff1642109392505050565b60006105e661233683613749565b61375c565b60006105e660406004845b919061379d565b6000612358846137be565b60008181526101306020526040902054909150760100000000000000000000000000000000000000000000900464ffffffffff16156123c3576040517fa789712900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808463ffffffff1681526020016123e38661233b565b63ffffffff1681526020016123f7866137cc565b64ffffffffff16815260200161240c866137db565b64ffffffffff16815260200161242761012f8054905061201e565b63ffffffff16815260200161243a612967565b64ffffffffff90811682526020918201949094526000838152610130825260408082208451815494860151928601516060870151608088015160a08901518b16760100000000000000000000000000000000000000000000027fffffffffff0000000000ffffffffffffffffffffffffffffffffffffffffffff63ffffffff928316720100000000000000000000000000000000000002167fffffffffff000000000000000000ffffffffffffffffffffffffffffffffffff938d166d0100000000000000000000000000027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff95909d166801000000000000000002949094167fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff978316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909a16929095169190911797909717949094169190911797909717919091169590951791909117845560c09091015160019384015561012f8054938401815590527f232da9e50dad2971456a78fb5cd6ff6b75019984d6e918139ce990999420f979909101555050565b60006105e6602080845b91906137ea565b604080516060810182526000808252602082018190529181019190915250604080516060810182526101605464ffffffffff80821683526501000000000082041660208301526a0100000000000000000000900463ffffffff169181019190915261266a612967565b64ffffffffff1681527f000000000000000000000000000000000000000000000000000000000000000063ffffffff9081167f000000000000000000000000000000000000000000000000000000000000000091909116148015906126cd575083155b80156126dc57508261015f5414155b15611ee0576126e9612967565b64ffffffffff16602082015263ffffffff821660408083019190915261015f849055517fc8ba82607c756c8ae67c7e47c27ade0b0718d492495044a1f8619663f26ebaa39061273b9085815260200190565b60405180910390a19392505050565b815160005b8181101561296157600084828151811061276b5761276b614c9c565b602002602001015190506000612790826fffffffffffffffffffffffffffffffff1690565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff16036127cc57505061294f565b63ffffffff81811660009081526101636020908152604091829020825160608101845290546bffffffffffffffffffffffff8082168084526c0100000000000000000000000083049096168385015270010000000000000000000000000000000090910464ffffffffff1693820193909352929085901c909116908103612856575050505061294f565b6040518060600160405280826bffffffffffffffffffffffff1681526020018863ffffffff168152602001612889612967565b64ffffffffff90811690915263ffffffff9485166000908152610163602090815260409182902084518154928601519590930151909316700100000000000000000000000000000000027fffffffffffffffffffffff0000000000ffffffffffffffffffffffffffffffff949097166c01000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009091166bffffffffffffffffffffffff909216919091171791909116939093179092555050505b8061295981614f3a565b91505061274f565b50505050565b6000610d5a426138f4565b6033546001600160a01b03163314610fee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161106e565b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561108081613971565b600260fb5403612a4f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161106e565b600260fb55565b60006105e6612a6483613749565b6139db565b60006105e6612a7a82601185612346565b613a1c565b600080612a8b83612a69565b90506000612aab8270ffffffffffffffffffffffffffffffffff16612db1565b6001811115612abc57612abc614693565b03612b0057611ee0612ae78270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612af66112ed87612de4565b613a60565b613a86565b611ee0612b268270ffffffffffffffffffffffffffffffffff1660009081526020902090565b612afb612b3a612b3587612de4565b613ad2565b613b13565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526000612bdc600160408b901c68ffffffffffffffffff16612b999190614f72565b63ffffffff168989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060209250613b23915050565b90506000612c2b8260608c901c64ffffffffff168888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250613bcb915050565b600081815261013060209081526040808320815160e081018352815463ffffffff8082168352640100000000820481169583019590955264ffffffffff6801000000000000000082048116948301949094526d010000000000000000000000000081048416606083015272010000000000000000000000000000000000008104909416608082015276010000000000000000000000000000000000000000000090930490911660a0830181905260019091015460c083015290955091925003612d20576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d2b9061221c565b15612d62576040517f6893014300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251612d6d90612251565b15612da4576040517f18989d5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050979650505050505050565b6000612dd08270ffffffffffffffffffffffffffffffffff1660801c90565b60ff1660018111156105e6576105e6614693565b600081611ee081613c2b565b6000612dfb82613c42565b61209a576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080612e3d83613c77565b905067ffffffffffffffff602082901c81169085161015612e8a576040517fed43c3a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612e9b612e9885613c93565b90565b90508467ffffffffffffffff165a11612ee0576040517faa6c898500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000606088901c64ffffffffff16604089901c68ffffffffffffffffff16612f07876125f0565b8977ffffffffffffffffffffffffffffffffffffffffffffffff8716612f34612f2f8b613ca2565b613cc5565b604051602401612f4996959493929190614f8f565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f032f287e000000000000000000000000000000000000000000000000000000001790529050612fc36001600160a01b03831667ffffffffffffffff8816600084613d04565b93505050505b949350505050565b60006105e6612e9882602085612346565b600080612fee83613ad2565b90506000613031606087901c64ffffffffff166040805163ffffffff9092166020830152810187905260600160408051601f198184030181529190528390613d36565b905060006130686001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683613e64565b9050805160201415806130ad575061307f83613ea8565b7fffffffff00000000000000000000000000000000000000000000000000000000166130aa82614fcc565b14155b156130e4576040517ff8b4221800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff161461314e57506000610bc4565b8260000361315e57506000610bc4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636b47b3bc87878661319a8988613317565b6040518563ffffffff1660e01b81526004016131b9949392919061500e565b6020604051808303816000875af11580156131d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fc919061503d565b9695505050505050565b600160fb55565b600054610100900460ff1661328a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613eb7565b600054610100900460ff1661330f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee613f3d565b600082815261012e60205260409020546060906001600160a01b03168061333f575060608201515b600061012f846020015163ffffffff168154811061335f5761335f614c9c565b6000918252602080832090910154808352610130909152604082205490925061338d9063ffffffff1661215e565b5085516040808801516060808a0151835160e095861b7fffffffff0000000000000000000000000000000000000000000000000000000090811660208301527f000000000000000000000000000000000000000000000000000000000000000090961b9095166024860152602885018c90526048850188905260f89290921b7fff0000000000000000000000000000000000000000000000000000000000000016606885015284811b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116606986015288821b8116607d86015291901b1660918301528051608581840301815260a590920190529091506131fc565b60006105e661349983613749565b613fba565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff166134d083613ffb565b63ffffffff161461350d576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061351883614009565b600081815261012d602090815260408083208151608081018352905463ffffffff80821680845264010000000083049091169483019490945268010000000000000000810460ff169282019290925269010000000000000000009091046001600160a01b031660608201529293509003613596575060009392505050565b805163ffffffff166135a785614018565b63ffffffff161415806135cc5750806040015160ff166135c685614026565b60ff1614155b156135db575060009392505050565b60006135e685614035565b60008181526101306020526040812054919250906136099063ffffffff1661215e565b50905061012f836020015163ffffffff168154811061362a5761362a614c9c565b90600052602060002001548214158061365d5750806001600160a01b031661365187614044565b6001600160a01b031614155b1561366e5750600095945050505050565b600084815261012e60205260409020546001600160a01b0316806136e15783606001516001600160a01b03166136a388614053565b6001600160a01b03161480156136d6575083606001516001600160a01b03166136cb88614060565b6001600160a01b0316145b979650505050505050565b60006136ec88614060565b9050816001600160a01b031661370189614053565b6001600160a01b031614801561373d57506001600160a01b038116158061373d575084606001516001600160a01b0316816001600160a01b0316145b98975050505050505050565b805160009060208301612fc9818361406d565b6000613767826140d0565b61209a576040517feb92662c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806137ab8585856137ea565b602084900360031b1c9150509392505050565b60006105e6816020846125fa565b60006105e66044600584612346565b60006105e66049600584612346565b6000816000036137fc57506000611ee0565b6020821115613837576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416613854838561505f565b111561388c576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b600061389d8660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b600064ffffffffff82111561209a5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201527f3020626974730000000000000000000000000000000000000000000000000000606482015260840161106e565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006139e6826140ef565b61209a576040517fd082b2a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600160ff608084901c16111561209a576040517f58ebbfbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6613a7d613a7184612fd1565b60009081526020902090565b612afb846141a4565b600082158015613a94575081155b15613aa1575060006105e6565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506105e6565b6000613add826141b4565b61209a576040517f9d46362800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e6826141f0565b6141f0565b815160009082811115613b62576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84915060005b81811015613b9f57613b9583868381518110613b8657613b86614c9c565b6020026020010151898461421b565b9250600101613b68565b50805b83811015613bc157613bb7836000898461421b565b9250600101613ba2565b5050949350505050565b60006101fe600183901b1660408110613c10576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613c1c8787614244565b90506136d68282876006613b23565b60006105e6613c3b60118361505f565b83906142a5565b60006018613c526020604061505f565b613c5c919061505f565b6fffffffffffffffffffffffffffffffff8316101592915050565b60006105e6612e98613c8b6020604061505f565b601885612346565b60006105e660406020846125fa565b60006105e66018613cb56020604061505f565b613c3b919061505f565b906142a5565b60405180613cd6836020830161430b565b506fffffffffffffffffffffffffffffffff83166000601f8201601f19168301602001604052509052919050565b6000846001600160a01b03163b600003613d2057506000612fc9565b600080835160208501868989f195945050505050565b6060613d448251601f161590565b613d7a576040517fd49e9d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160038082526080820190925260009160208201606080368337019050509050613dec613da985613ea8565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091166020820152602401604051602081830303815290604052613749565b81600081518110613dff57613dff614c9c565b602002602001018181525050613e1483613749565b81600181518110613e2757613e27614c9c565b602002602001018181525050613e3c846143b4565b81600281518110613e4f57613e4f614c9c565b602002602001018181525050612fc9816143c2565b6060611ee0838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250614400565b600081611ee0818360046137ea565b600054610100900460ff16613f345760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b610fee336129cc565b600054610100900460ff166132065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161106e565b6000613fc5826144e7565b61209a576040517f76b4e13c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105e660048084612346565b60006105e660086020846125fa565b60006105e681600484612346565b60006105e66048600184612346565b60006105e660286020846125fa565b60006105e66049835b90614503565b60006105e6605d8361404d565b60006105e660718361404d565b60008061407a838561505f565b905060405181111561408a575060005b806000036140c4576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317612fc9565b6000604e6fffffffffffffffffffffffffffffffff83165b1492915050565b60006fffffffffffffffffffffffffffffffff821661410f60118361505f565b81101561411f5750600092915050565b600061412a84614511565b9050600160ff608083901c161115614146575060009392505050565b600061416c61415483613a1c565b70ffffffffffffffffffffffffffffffffff16612db1565b600181111561417d5761417d614693565b0361419357612fc961418e85613c2b565b613c42565b612fc961419f85613c2b565b6141b4565b60006105e6613b1e602084613cbf565b60006fffffffffffffffffffffffffffffffff821660048110156141db5750600092915050565b611ee06141e9600483614e34565b601f161590565b6000806141fd8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b6000600183831c16810361423a576142338585613a86565b9050612fc9565b6142338486613a86565b6000828260405160200161428792919091825260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015260240190565b60405160208183030381529060405280519060200120905092915050565b60006fffffffffffffffffffffffffffffffff8316808311156142f4576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fc9836143028660801c90565b0184830361406d565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c9080851015614365576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa9050806143a8576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b84176136d6565b600081611ee08160046142a5565b6040518060006143d5846020840161451f565b6fffffffffffffffffffffffffffffffff16601f8101601f1916830160200160405290915250919050565b6060824710156144785760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161106e565b600080866001600160a01b031685876040516144949190615072565b60006040518083038185875af1925050503d80600081146144d1576040519150601f19603f3d011682016040523d82523d6000602084013e6144d6565b606091505b50915091506136d6878383876145c3565b600060856fffffffffffffffffffffffffffffffff83166140e8565b6000611ee08383601461379d565b60006105e68282601161379d565b6040516000908083101561455f576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b85518110156145b657600086828151811061458057614580614c9c565b602002602001015190506145968184880161430b565b506fffffffffffffffffffffffffffffffff169190910190600101614563565b50608084901b8117610bc4565b6060831561463257825160000361462b576001600160a01b0385163b61462b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161106e565b5081612fc9565b612fc983838151156146475781518083602001fd5b8060405162461bcd60e51b815260040161106e91906149f5565b6001600160a01b038116811461108057600080fd5b60006020828403121561468857600080fd5b8135611ee081614661565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051600681106146d4576146d4614693565b825260208181015163ffffffff9081169184019190915260409182015116910152565b606081016105e682846146c2565b60006020828403121561471757600080fd5b5035919050565b60005b83811015614739578181015183820152602001614721565b50506000910152565b6000815180845261475a81602086016020860161471e565b601f01601f19169290920160200192915050565b6040815260006147816040830185614742565b8281036020840152610bc48185614742565b6001600160a01b038316815260808101611ee060208301846146c2565b63ffffffff8116811461108057600080fd5b6000602082840312156147d457600080fd5b8135611ee0816147b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614837576148376147df565b604052919050565b600067ffffffffffffffff821115614859576148596147df565b50601f01601f191660200190565b600082601f83011261487857600080fd5b813561488b6148868261483f565b61480e565b8181528460208386010111156148a057600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156148d557600080fd5b85356148e0816147b0565b94506020868101359450604087013567ffffffffffffffff8082111561490557600080fd5b6149118a838b01614867565b955060608901359450608089013591508082111561492e57600080fd5b818901915089601f83011261494257600080fd5b813581811115614954576149546147df565b8060051b915061496584830161480e565b818152918301840191848101908c84111561497f57600080fd5b938501935b838510156149bf57843592506fffffffffffffffffffffffffffffffff831683146149af5760008081fd5b8282529385019390850190614984565b8096505050505050509295509295909350565b6003811061108057611080614693565b602081016149ef836149d2565b91905290565b602081526000611ee06020830184614742565b60008083601f840112614a1a57600080fd5b50813567ffffffffffffffff811115614a3257600080fd5b6020830191508360208260051b8501011115614a4d57600080fd5b9250929050565b60008060208385031215614a6757600080fd5b823567ffffffffffffffff811115614a7e57600080fd5b614a8a85828601614a08565b90969095509350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015614b1c578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805115158452870151878401879052614b0987850182614742565b9588019593505090860190600101614abd565b509098975050505050505050565b60008060408385031215614b3d57600080fd5b8235614b48816147b0565b91506020830135614b58816147b0565b809150509250929050565b600080600080600080600060a0888a031215614b7e57600080fd5b873567ffffffffffffffff80821115614b9657600080fd5b614ba28b838c01614867565b985060208a0135915080821115614bb857600080fd5b614bc48b838c01614a08565b909850965060408a0135915080821115614bdd57600080fd5b614be98b838c01614a08565b909650945060608a0135915060ff82168214614c0457600080fd5b9092506080890135908082168214614c1b57600080fd5b508091505092959891949750929550565b81516060820190614c3c816149d2565b80835250602083015164ffffffffff8082166020850152806040860151166040850152505092915050565b600060208284031215614c7957600080fd5b813567ffffffffffffffff811115614c9057600080fd5b612fc984828501614867565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215614cdd57600080fd5b815167ffffffffffffffff811115614cf457600080fd5b8201601f81018413614d0557600080fd5b8051614d136148868261483f565b818152856020838501011115614d2857600080fd5b610bc482602083016020860161471e565b600060208284031215614d4b57600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614d8657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614dc557600080fd5b83018035915067ffffffffffffffff821115614de057600080fd5b602001915036819003821315614a4d57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105e6576105e6614e05565b64ffffffffff818116838216019080821115614e6557614e65614e05565b5092915050565b600060608284031215614e7e57600080fd5b6040516060810181811067ffffffffffffffff82111715614ea157614ea16147df565b8060405250809150825160068110614eb857600080fd5b81526020830151614ec8816147b0565b60208201526040830151614edb816147b0565b6040919091015292915050565b600060608284031215614efa57600080fd5b611ee08383614e6c565b60008060808385031215614f1757600080fd5b8251614f2281614661565b9150614f318460208501614e6c565b90509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f6b57614f6b614e05565b5060010190565b63ffffffff828116828216039080821115614e6557614e65614e05565b600063ffffffff8089168352808816602084015286604084015285606084015280851660808401525060c060a083015261373d60c0830184614742565b80516020808301519190811015610c75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600063ffffffff8087168352808616602084015250836040830152608060608301526131fc6080830184614742565b60006020828403121561504f57600080fd5b81518015158114611ee057600080fd5b808201808211156105e6576105e6614e05565b60008251614d8681846020870161471e56fea2646970667358221220a616f11f6c8333fe4015a6de25a4be94acb62d7e000bb8d6e82c4ae8429713c664736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"301495:268:0:-:0;;;301593:111;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;263591:219;;;;;;;;;;;;;-1:-1:-1;;;263591:219:0;;;;100839:32;;301671:6;;301679:13;;301694:6;;301671;301679:13;301694:6;263591:219;301671:6;263591:219;101105:24;101119:8;101105:24;:::i;:::-;101097:32;;;;;;100793:343;255094:22:::1;:20;;;;;:22;;:::i;:::-;255080:36;::::0;;::::1;;::::0;255126:30:::1;;::::0;-1:-1:-1;;;;;;263751:28:0;;::::1;;::::0;263789:14:::1;;::::0;-1:-1:-1;301495:268:0;;-1:-1:-1;;;;;;;301495:268:0;102680:98;102722:6;102747:24;:13;:22;;;;;:24;;:::i;:::-;102740:31;;102680:98;:::o;68801:187::-;68857:6;68892:16;68883:25;;;68875:76;;;;-1:-1:-1;;;68875:76:0;;1155:2:1;68875:76:0;;;1137:21:1;1194:2;1174:18;;;1167:30;1233:34;1213:18;;;1206:62;-1:-1:-1;;;1284:18:1;;;1277:36;1330:19;;68875:76:0;;;;;;;;-1:-1:-1;68975:5:0;68801: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:450::-;283:6;291;299;352:2;340:9;331:7;327:23;323:32;320:52;;;368:1;365;358:12;320:52;400:9;394:16;450:10;443:5;439:22;432:5;429:33;419:61;;476:1;473;466:12;419:61;499:5;-1:-1:-1;523:49:1;568:2;553:18;;523:49;:::i;:::-;513:59;;591:49;636:2;625:9;621:18;591:49;:::i;:::-;581:59;;196:450;;;;;:::o;651:297::-;769:12;;816:4;805:16;;;799:23;;769:12;834:16;;831:111;;;928:1;924:6;914;908:4;904:17;901:1;897:25;893:38;886:5;882:50;873:59;;831:111;;651:297;;;:::o;953:402::-;301495:268:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"301495:268:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;265499:122;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;296850:880;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;265661:138::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;290904:53::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3341:10:1;3329:23;;;3311:42;;3299:2;3284:18;290904:53:0;3167:192:1;292769:1409:0;;;;;;:::i;:::-;;:::i;:::-;;;6430:14:1;;6423:22;6405:41;;6393:2;6378:18;292769:1409:0;6265:187:1;277015:421:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;296704:99::-;296783:6;:13;296704:99;;;7161:25:1;;;7149:2;7134:18;296704:99:0;7015:177:1;290821:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;7403:12:1;7442:15;;;7424:34;;7494:15;;;;7489:2;7474:18;;7467:43;7558:10;7546:23;7526:18;;;7519:51;7381:2;7366:18;290821:35:0;7197:379:1;276521:139:0;;;;;;:::i;:::-;276591:15;276625:19;;;:9;:19;;;;;:28;;;;;;;276521:139;101142:401;101313:28;;;;;;;;;101326:7;101313:28;;101335:5;101313:28;;;;101142:401;;;;;;;:::i;298748:238::-;;;:::i;98489:1352::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;264546:579::-;;;;;;:::i;:::-;;:::i;:::-;;255388:57;;;:::i;254506:37::-;;;;;262677;;;;;;;;-1:-1:-1;;;;;10508:55:1;;;10490:74;;10478:2;10463:18;262677:37:0;10344:226:1;226826:212:0;;;:::i;272914:3233::-;;;;;;:::i;:::-;;:::i;254389:35::-;;;;;223157:85;223229:6;;-1:-1:-1;;;;;223229:6:0;223157:85;;291790:622;;;;;;:::i;:::-;;:::i;264158:348::-;;;;;;:::i;:::-;;:::i;294527:1754::-;;;:::i;297777:924::-;;;;;;:::i;:::-;;:::i;:::-;;;;12131:26:1;12119:39;;;12101:58;;12190:2;12175:18;;12168:34;;;;12074:18;297777:924:0;11900:308:1;277476:350:0;;;;;;:::i;:::-;;:::i;265839:138::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;276700:275::-;;;;;;:::i;:::-;;:::i;225939:99::-;226018:13;;-1:-1:-1;;;;;226018:13:0;225939:99;;226231:178;;;;;;:::i;:::-;;:::i;262755:30::-;;;;;265499:122;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;265595:19:0;265608:5;265595:12;:19::i;:::-;265588:26;265499:122;-1:-1:-1;;265499:122:0:o;296850:880::-;296987:6;:13;296912:23;;;;296978:22;;296974:52;;297009:17;;;;;;;;;;;;;;296974:52;297036:16;297055:6;297062:5;297055:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;297109:19;;;:9;:19;;;;;;297078:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;297171:19;:26;;297055:13;;-1:-1:-1;297078:50:0;;297055:13;297171:19;297191:5;;297171:26;;;;;;:::i;:::-;;;;;;;;;;;297138:59;;;;;;;;;;;;;;;;;;;;;;;;;;;297220:241;297278:8;297311:9;:18;;;297351:8;:17;;;297396:8;:14;;;297436:8;:14;;;200250:72;;;;;;19017:19:1;;;;19052:12;;;19045:28;;;;19111:3;19107:16;;;;19125:66;19103:89;200219:12:0;19089::1;;19082:111;19316:3;19312:16;;;19212:66;19308:25;;;19294:12;;;19287:47;19368:16;;;19364:25;19350:12;;;19343:47;200250:72:0;;;;;;;;;19406:12:1;;;;200250:72:0;;;200030:299;297220:241;297207:254;;297609:13;297594:28;;:11;:28;;;297590:134;;297695:17;;;;297653:60;;;;;;;;7161:25:1;;;;297669:5:0;-1:-1:-1;;;;;297653:41:0;;;;7134:18:1;;297653:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;297653:60:0;;;;;;;;;;;;:::i;:::-;297638:75;;297590:134;296964:766;;;296850:880;;;:::o;265661:138::-;-1:-1:-1;;;;;;;;265717:13:0;-1:-1:-1;;;;;;;;;;;;;;;265776:16:0;265786:5;265776:9;:16::i;:::-;265769:23;;;;265661:138;;;:::o;292769:1409::-;292979:16;263523:10;-1:-1:-1;;;;;263537:5:0;263523:19;;263519:48;;263551:16;;;;;;;;;;;;;;263519:48;293129:33:::1;293150:11;293129:20;:33::i;:::-;293125:63;;;293171:17;;;;;;;;;;;;;;293125:63;293202:34;293224:11;293202:21;:34::i;:::-;293198:70;;;293245:23;;;;;;;;;;;;;;293198:70;293395:15;293413:30;:10;:28;:30::i;:::-;293395:48;;293518:15;293536:11;:3;:9;:11::i;:::-;293573:33;::::0;;::::1;;::::0;;;:20:::1;:33;::::0;;;;;293518:29;;-1:-1:-1;293573:33:0;;::::1;293561:45:::0;;::::1;;293557:73;;293615:15;;;;;;;;;;;;;;293557:73;293640:33;::::0;;::::1;;::::0;;;:20:::1;:33;::::0;;;;:44;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;293769::::1;293786:3:::0;293640:33;293804:8;293769:16:::1;:44::i;:::-;293823:19;293848:63;;;;;;;;293874:9;293848:63;;;;293895:14;:3;:12;:14::i;:::-;293848:63:::0;;293823:89;;::::1;::::0;;::::1;::::0;;-1:-1:-1;293823:89:0;;;::::1;::::0;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;::::1;::::0;294017:15:::1;:13;:15::i;:::-;293998:34;;294055:51;294070:11;294083:9;294094:11;294055:14;:51::i;:::-;294042:64:::0;;:10:::1;:64:::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;294116:34:::1;294129:7:::0;294138:11;294116:12:::1;:34::i;:::-;294167:4;294160:11;;;;;263577:1;292769:1409:::0;;;;;;;:::o;277015:421::-;277082:20;277144:25;;;:12;:25;;;;;;;;277114:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;277114:55:0;;;;;;;277183:31;277179:251;;-1:-1:-1;277237:21:0;;277015:421;-1:-1:-1;;277015:421:0:o;277179:251::-;277318:1;277279:27;;;:14;:27;;;;;;-1:-1:-1;;;;;277279:27:0;:41;277275:155;;-1:-1:-1;277343:20:0;;277015:421;-1:-1:-1;;277015:421:0:o;277275:155::-;-1:-1:-1;277401:18:0;;277015:421;-1:-1:-1;;277015:421:0:o;277275:155::-;277104:332;277015:421;;;:::o;298748:238::-;298796:7;298907:13;298892:28;;:11;:28;;;:87;;-1:-1:-1;298965:14:0;;;298748:238::o;298892:87::-;298937:12;-1:-1:-1;;;;;298923:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;298885:94;;298748:238;:::o;98489:1352::-;98549:27;98605:5;;98641:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;98641:20:0;;;;;;;;;;;;;;;;98627:34;;98671:19;98705:9;98700:1135;98724:6;98720:1;:10;98700:1135;;;98755:5;;98761:1;98755:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;98747:16;;98777:20;98800:11;98812:1;98800:14;;;;;;;;:::i;:::-;;;;;;;98777:37;;99157:4;-1:-1:-1;;;;;99149:26:0;99176:5;:14;;;;;;;;:::i;:::-;99149:42;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;99128:17:0;;;99111:80;;;;;;99464:19;;99461:38;99451:301;;99628:66;99622:4;99615:80;99729:4;99723;99716:18;99451:301;-1:-1:-1;99807:3:0;;98700:1135;;;;98578:1263;;98489:1352;;;;:::o;264546:579::-;263406:10;-1:-1:-1;;;;;263420:12:0;263406:26;;263402:62;;263441:23;;;;;;;;;;;;;;263402:62;264711:17:::1;264731:29;:27;:29::i;:::-;264770:23;::::0;;::::1;;::::0;;;:9:::1;:23;::::0;;;;:50;;264830:47:::1;::::0;::::1;::::0;::::1;::::0;;;;;264801:19:::1;264830:47:::0;;;264711:49;;-1:-1:-1;264973:15:0;::::1;::::0;264969:150:::1;;265004:21;::::0;::::1;265033:16;265004:21:::0;;;:9:::1;:21;::::0;;;;:45;;265063;;;::::1;::::0;::::1;;;::::0;;264969:150:::1;264636:489;264546:579:::0;;:::o;255388:57::-;223050:13;:11;:13::i;:::-;255388:57::o;226826:212::-;226018:13;;194999:10;;-1:-1:-1;;;;;226018:13:0;226925:24;;226917:78;;;;-1:-1:-1;;;226917:78:0;;15774:2:1;226917:78:0;;;15756:21:1;15813:2;15793:18;;;15786:30;15852:34;15832:18;;;15825:62;15923:11;15903:18;;;15896:39;15952:19;;226917:78:0;;;;;;;;;227005:26;227024:6;227005:18;:26::i;:::-;226868:170;226826:212::o;272914:3233::-;192930:21;:19;:21::i;:::-;273205:15:::1;273223:26;:10;:24;:26::i;:::-;273205:44;;273259:13;273275:16;:7;:14;:16::i;:::-;273259:32;;273301:15;273319:14;:7;:12;:14::i;:::-;273301:32:::0;-1:-1:-1;273399:35:0::1;273423:11;273399:35;149262:5:::0;153035:42;;;;;273399:35:::1;;;273395:76;;273443:28;;;;;;;;;;;;;;273395:76;273541:30;273560:11;273541:30;149045:6:::0;152480:37;;;;;273541:30:::1;;::::0;273537:66:::1;;273580:23;;;;;;;;;;;;;;273537:66;273672:27;273702:21:::0;;;:12:::1;:21;::::0;;;;;;;;273672:51;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;::::1;;::::0;;::::1;::::0;;;;;;::::1;;;::::0;;;;;;;;;::::1;-1:-1:-1::0;;;;;273672:51:0::1;::::0;;;;;;273737:31;273733:61:::1;;273777:17;;;;;;;;;;;;;;273733:61;273837:28;273868:70;273886:6;273894:7;273903:11;;273916:9;;273927:10;273868:17;:70::i;:::-;273837:101;;273997:21;274039:8;:20;;;274021:38;;:15;:38;;;;:::i;:::-;273997:62:::0;-1:-1:-1;274073:41:0::1;::::0;;;::::1;274069:79;;;274123:25;;;;;;;;;;;;;;274069:79;274158:18;::::0;;274261:13:::1;:6;:11;;;:13::i;:::-;:33;;;;;;;;:::i;:::-;::::0;274257:527:::1;;274397:23;274423:34;:14;:7;:12;:14::i;:::-;:32;:34::i;:::-;274397:60;;274481:65;274501:6;274509:13;274524:8;274534:11;274481:19;:65::i;:::-;274471:75;;274585:18;:11;:16;:18::i;:::-;274560:44;;274296:319;274257:527;;;274712:61;274735:6;274743:13;274758:14;:7;:12;:14::i;:::-;274712:22;:61::i;:::-;274702:71;;274257:527;274797:15:::0;;:20:::1;;:15;:20:::0;274793:1020:::1;;274937:33;149045:6:::0;152480:37;;;274937:33;;;;275005:14:::1;::::0;::::1;::::0;274984:35:::1;:18;::::0;::::1;:35:::0;275033:32:::1;::::0;::::1;:19;::::0;::::1;:32:::0;275079:314;::::1;;;275224:10;275204:17;::::0;::::1;:30:::0;275079:314:::1;;;275342:23;::::0;;;:14:::1;:23;::::0;;;;:36;;;::::1;275368:10;275342:36;::::0;;275079:314:::1;275406:21;::::0;;;:12:::1;:21;::::0;;;;;;;;:32;;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;275406:32:0::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;::::1;::::0;;274793:1020:::1;;;275474:7;275469:36;;275490:15;;;;;;;;;;;;;;275469:36;275746:10;275726:17;::::0;::::1;:30:::0;;;275770:21:::1;::::0;;;:12:::1;:21;::::0;;;;;;;;:32;;;;;;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;;;;275770:32:0::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;;;::::1;::::0;;274793:1020:::1;275827:43;::::0;6430:14:1;;6423:22;6405:41;;275853:7:0;;275827:43:::1;149045:6:::0;152480:37;;;275827:43;;::::1;::::0;6393:2:1;6378:18;275827:43:0::1;;;;;;;275885:84;275898:8;:20;;;275920:8;:17;;;275939:7;275948:10;275960:8;275885:12;:84::i;:::-;275880:261;;276097:33;::::0;;16478:25:1;;;16534:2;16519:18;;16512:34;;;276097:33:0::1;::::0;16451:18:1;276097:33:0::1;;;;;;;275880:261;273121:3026;;;;;;;;192972:20:::0;192212:1;193478:7;:22;193298:209;192972:20;272914:3233;;;;;;;:::o;291790:622::-;157233:19;157256:13;;;;;;157255:14;;157301:34;;;;-1:-1:-1;157319:12:0;;157334:1;157319:12;;;;:16;157301:34;157300:108;;;-1:-1:-1;157380:4:0;90357:19;:23;;;157341:66;;-1:-1:-1;157390:12:0;;;;;:17;157341:66;157279:201;;;;-1:-1:-1;;;157279:201:0;;16759:2:1;157279:201:0;;;16741:21:1;16798:2;16778:18;;;16771:30;16837:34;16817:18;;;16810:62;16908:16;16888:18;;;16881:44;16942:19;;157279:201:0;16557:410:1;157279:201:0;157490:12;:16;;;;157505:1;157490:16;;;157516:65;;;;157550:13;:20;;;;;;;;157516:65;291920:21:::1;:19;:21::i;:::-;291990:24;:22;:24::i;:::-;292093:13;292078:28;;:11;:28;;;292074:237;;292122:14;:26:::0;;;292162:68:::1;::::0;;;;::::1;::::0;::::1;7161:25:1::0;;;292192:12:0::1;-1:-1:-1::0;;;;;292162:57:0::1;::::0;::::1;::::0;7134:18:1;;292162:68:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;292271:29;:27;:29::i;:::-;292244:10;:56:::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;292074:237:::1;157605:14:::0;157601:99;;;157651:5;157635:21;;;;;;157675:14;;-1:-1:-1;17124:36:1;;157675:14:0;;17112:2:1;17097:18;157675:14:0;;;;;;;157601:99;157223:483;291790:622;:::o;264158:348::-;263406:10;-1:-1:-1;;;;;263420:12:0;263406:26;;263402:62;;263441:23;;;;;;;;;;;;;;263402:62;264254:15:::1;264272:29;:27;:29::i;:::-;264254:47;;264311:27;264341:77;;;;;;;;264362:19;264341:77;;;;;;;;:::i;:::-;::::0;;::::1;::::0;::::1;;::::0;;::::1;::::0;;;;-1:-1:-1;264341:77:0;;;;;;;264428:21:::1;::::0;::::1;::::0;;:9:::1;:21:::0;;;;:30;;;;264311:107;;-1:-1:-1;264311:107:0;;264428:21;;:30;::::1;::::0;;::::1;::::0;::::1;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;264428:30:0::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;::::1;;;::::0;;;;;;::::1;::::0;;;264468:22:::1;::::0;::::1;264428:30;264468:22:::0;;;:9:::1;:22:::0;;;;:31;;;;264493:6;;264468:22;:31;:22;;:31;::::1;264428:30;264468:31:::0;::::1;::::0;::::1;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;264468:31:0::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;;::::1;;::::0;;::::1;;::::0;;;;;;;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;;;;264158:348:0:o;294527:1754::-;294568:16;294712:13;294697:28;;:11;:28;;;294693:46;;-1:-1:-1;294734:5:0;;294527:1754::o;294693:46::-;294749:15;294781:12;-1:-1:-1;;;;;294767:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;294834:14;;294749:57;;-1:-1:-1;294938:18:0;;;294934:36;;294965:5;294958:12;;;;294527:1754;:::o;294934:36::-;294980:44;;;;;;;;295014:10;294980:44;;;;;;;;;;;;;;;;;;;;;;;;;;;295202:40;;:20;:40::i;:::-;295198:202;;;-1:-1:-1;;295339:14:0;:24;-1:-1:-1;295384:5:0;;294527:1754::o;295198:202::-;295636:41;295658:6;:18;;;295636:21;:41::i;:::-;295632:151;;;295768:4;295761:11;;;;;294527:1754;:::o;295632:151::-;295853:20;;;;295907:15;;295853:51;;27349:6;;295853:51;:::i;:::-;:69;;;295849:179;;;296013:4;296006:11;;;;;294527:1754;:::o;295849:179::-;296186:66;;;;;;;;7161:25:1;;;296216:12:0;-1:-1:-1;;;;;296186:57:0;;;;7134:18:1;;296186:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;296269:5;296262:12;;;;;294527:1754;:::o;297777:924::-;297921:22;;;;297835:15;297921:22;;;:14;:22;;;;;;;;297884:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;297835:15;;;;297884:59;298276:30;;;;:94;;;298323:47;298344:13;:25;;;298323:20;:47::i;:::-;298322:48;298276:94;:159;;;;;298387:48;298409:13;:25;;;298387:21;:48::i;:::-;298386:49;298276:159;298259:315;;;298470:21;;298538:25;;;;298470:21;;-1:-1:-1;298520:43:0;;;;:15;:43;:::i;:::-;298505:58;;298259:315;297874:827;297777:924;;;:::o;277476:350::-;277580:27;277610:25;;;:12;:25;;;;;;;;277580:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;277580:55:0;277544:24;277580:55;;;;;;;277544:24;277580:55;;277733:20;;277729:35;;-1:-1:-1;;277755:9:0;;;;;;;;;-1:-1:-1;277755:9:0;;;277476:350;-1:-1:-1;277476:350:0:o;277729:35::-;277781:38;277797:11;277810:8;277781:15;:38::i;:::-;277774:45;277476:350;-1:-1:-1;;;277476:350:0:o;265839:138::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;265949:21:0;;;;;;;:9;:21;;;;;;;265942:28;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;265839:138;-1:-1:-1;;265839:138:0:o;276700:275::-;276773:12;276924:44;276940:27;:11;:25;:27::i;:::-;276924:15;:44::i;226231:178::-;223050:13;:11;:13::i;:::-;226320::::1;:24:::0;;-1:-1:-1;;;;;226320:24:0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;226384:7:::1;223229:6:::0;;-1:-1:-1;;;;;223229:6:0;;223157:85;226384:7:::1;-1:-1:-1::0;;;;;226359:43:0::1;;;;;;;;;;;226231:178:::0;:::o;102680:98::-;102722:6;102747:24;:13;68801:187;68857:6;68892:16;68883:25;;;68875:76;;;;-1:-1:-1;;;68875:76:0;;17552:2:1;68875:76:0;;;17534:21:1;17591:2;17571:18;;;17564:30;17630:34;17610:18;;;17603:62;17701:8;17681:18;;;17674:36;17727:19;;68875:76:0;17350:402:1;68875:76:0;-1:-1:-1;68975:5:0;68801:187::o;266370:150::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;266467:46:0;;;;;-1:-1:-1;;;;;10508:55:1;;;266467:46:0;;;10490:74:1;266481:12:0;266467:39;;;;10463:18:1;;266467:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;266641:166::-;-1:-1:-1;;;;;;;;266698:13:0;-1:-1:-1;;;;;;;;;;;;;;;266757:43:0;;;;;;;;7161:25:1;;;266771:12:0;-1:-1:-1;;;;;266757:36:0;;;;7134:18:1;;266757:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;267192:150::-;267265:4;;267288:22;;;;;;;:9;:22;;;;;:27;;;:47;;;;;;;;:::i;:::-;;;;267192:150;-1:-1:-1;;267192:150:0:o;267795:524::-;267915:22;;;267869:4;267915:22;;;:9;:22;;;;;;267885:52;;;;;;;;;;267869:4;;267885:52;267915:22;267885:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;267885:52:0;268016:11;;:31;;;;;;;;:::i;:::-;;268012:49;;-1:-1:-1;268056:5:0;;267795:524;-1:-1:-1;;267795:524:0:o;268012:49::-;268134:6;:15;;;:20;;268153:1;268134:20;268130:38;;-1:-1:-1;268163:5:0;;267795:524;-1:-1:-1;;267795:524:0:o;268130:38::-;268270:17;;;;:42;;27688:8;;268270:42;:::i;:::-;268252:60;;:15;:60;;267795:524;-1:-1:-1;;;267795:524:0:o;200480:141::-;200552:11;200582:32;200600:13;:7;:11;:13::i;:::-;200582:17;:32::i;203288:218::-;203343:6;203441:57;199114:2;203495:1;203441:3;:12;:22;:57;:22;:57::i;282226:643::-;282326:12;282341:14;:3;:12;:14::i;:::-;282369:15;;;;:9;:15;;;;;:27;:15;;-1:-1:-1;282369:27:0;;;;;:32;282365:69;;282410:24;;;;;;;;;;;;;;282365:69;282531:304;;;;;;;;282571:11;282531:304;;;;;;282606:11;:3;:9;:11::i;:::-;282531:304;;;;;;282638:17;:3;:15;:17::i;:::-;282531:304;;;;;;282676:15;:3;:13;:15::i;:::-;282531:304;;;;;;282712:24;:6;:13;;;;:22;:24::i;:::-;282531:304;;;;;;282763:29;:27;:29::i;:::-;282531:304;;;;;;;;;;;;;;-1:-1:-1;282513:15:0;;;:9;:15;;;;;;:322;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;282845:6;:17;;;;;;;;;;;;;;-1:-1:-1;;282226:643:0:o;202778:149::-;202836:7;202862:58;199066:2;;202862:3;:12;:18;:58;:18;:58::i;299524:869::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;299686:19:0;;;;;;;;299695:10;299686:19;;;;;;;;;;;;;;;;;;;;;;;;;;;299798:29;:27;:29::i;:::-;299776:51;;;;300100:11;:28;;;;300115:13;300100:28;;;;;;;;:44;;;300133:11;300132:12;300100:44;:75;;;;;300166:9;300148:14;;:27;;300100:75;300096:291;;;300214:29;:27;:29::i;:::-;300191:52;;:20;;;:52;300257:32;;;:18;;;;:32;;;;300303:14;:26;;;300348:28;;;;;300320:9;7161:25:1;;7149:2;7134:18;;7015:177;300348:28:0;;;;;;;;299524:869;;;;;:::o;300468:857::-;300579:14;;300556:20;300603:716;300627:12;300623:1;:16;300603:716;;;300660:17;300680:7;300688:1;300680:10;;;;;;;;:::i;:::-;;;;;;;300660:30;;300704:13;300720:17;:8;:15;;153350:6;153149:216;300720:17;300704:33;;300821:11;300811:21;;:6;:21;;;300807:35;;300834:8;;;;300807:35;300893:22;;;;300856:34;300893:22;;;:14;:22;;;;;;;;;300856:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;145996:39;;;;;;;;301043:64;;301039:78;;301109:8;;;;;;301039:78;301205:103;;;;;;;;301229:7;301205:103;;;;;;301251:11;301205:103;;;;;;301277:29;:27;:29::i;:::-;301205:103;;;;;;;301164:22;;;;;;;;:14;:22;;;;;;;;;:144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;300603:716:0;300641:3;;;;:::i;:::-;;;;300603:716;;;;300546:779;300468:857;;:::o;102406:107::-;102455:6;102480:26;:15;:24;:26::i;223315:130::-;223229:6;;-1:-1:-1;;;;;223229:6:0;194999:10;223378:23;223370:68;;;;-1:-1:-1;;;223370:68:0;;20222:2:1;223370:68:0;;;20204:21:1;;;20241:18;;;20234:30;20300:34;20280:18;;;20273:62;20352:18;;223370:68:0;20020:356:1;226593:153:0;226682:13;226675:20;;;;;;226705:34;226730:8;226705:24;:34::i;193005:287::-;192255:1;193137:7;;:19;193129:63;;;;-1:-1:-1;;;193129:63:0;;20583:2:1;193129:63:0;;;20565:21:1;20622:2;20602:18;;;20595:30;20661:33;20641:18;;;20634:61;20712:18;;193129:63:0;20381:355:1;193129:63:0;192255:1;193267:7;:18;193005:287::o;257473:129::-;257541:7;257567:28;257581:13;:7;:11;:13::i;:::-;257567;:28::i;260011:186::-;260067:6;260092:98;260114:74;260067:6;25896:2;260114:7;:16;153149:216;260114:74;260092:20;:98::i;259113:522::-;259167:7;259272:14;259289:16;:7;:14;:16::i;:::-;259272:33;-1:-1:-1;259386:16:0;259368:14;:7;:12;;;:14::i;:::-;:34;;;;;;;;:::i;:::-;;259364:265;;259425:79;259446:14;:7;:12;;151371:20;151527:17;;;151643:2;151630:16;;;151319:343;259446:14;259462:41;:34;:14;:7;:12;:14::i;:34::-;:39;:41::i;:::-;259425:20;:79::i;259364:265::-;259542:76;259563:14;:7;:12;;151371:20;151527:17;;;151643:2;151630:16;;;151319:343;259563:14;259579:38;:31;:14;:7;:12;:14::i;:::-;:29;:31::i;:::-;:36;:38::i;285990:1462::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;286457:18:0;286478:82;286516:1;149148:5;152752:36;;;;;286499:18;;;;:::i;:::-;286478:82;;286519:7;286528:11;;286478:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24507:2:0;;-1:-1:-1;286478:20:0;;-1:-1:-1;;286478:82:0:i;:::-;286457:103;-1:-1:-1;286780:20:0;286803:77;286457:103;149045:6;152480:37;;;;;286858:9;;286803:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;286869:10:0;;-1:-1:-1;286803:25:0;;-1:-1:-1;;286803:77:0:i;:::-;286961:23;;;;:9;:23;;;;;;;;286950:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;286780:100:0;;-1:-1:-1;287051:25:0;287047:61;;287085:23;;;;;;;;;;;;;;287047:61;287220:20;;287199:42;;:20;:42::i;:::-;287195:72;;;287250:17;;;;;;;;;;;;;;287195:72;287392:20;;287370:43;;:21;:43::i;:::-;287366:79;;;287422:23;;;;;;;;;;;;;;287366:79;286228:1224;;285990:1462;;;;;;;;;:::o;152028:223::-;152080:11;152215:28;152235:6;152215:28;;148940:6;153936:26;;153757:213;152215:28;152203:41;;;;;;;;;;:::i;260275:145::-;260329:7;260366;260399:14;260366:7;260399:5;:14::i;239842:215::-;239909:11;239937:22;239951:7;239937:13;:22::i;:::-;239932:60;;239968:24;;;;;;;;;;;;;;278243:1395;278386:4;278627:15;278645:21;:11;:19;:21::i;:::-;278627:39;-1:-1:-1;278680:29:0;41913:5;43806:42;;;278680:29;;;;;;278676:58;;;278718:16;;;;;;;;;;;;;;278676:58;278801:17;278821:42;:23;:11;:21;:23::i;:::-;34796:3;34684:125;278821:42;278801:62;;278981:8;278968:21;;:9;:21;278964:53;;278998:19;;;;;;;;;;;;;;278964:53;279113:20;149045:6;152480:37;;;;;149148:5;152752:36;;;;;279297:20;:11;:18;:20::i;:::-;279335:13;279366:15;;;279401:29;:21;:11;:19;:21::i;:::-;:27;:29::i;:::-;279136:318;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;279136:318:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;279560:71:0;-1:-1:-1;;;;;279560:18:0;;:71;;;-1:-1:-1;279136:318:0;279560:18;:71::i;:::-;279553:78;;;;;278243:1395;;;;;;;:::o;241563:188::-;241625:4;241648:96;241668:74;241625:4;26088:2;241668:11;:20;153149:216;279813:1258;279915:4;280001:17;280021:21;:4;:19;:21::i;:::-;280001:41;-1:-1:-1;280118:20:0;280141:62;149045:6;152480:37;;;;;280160:42;;;21754:10:1;21742:23;;;280160:42:0;;;21724::1;21782:18;;21775:34;;;21697:18;;280160:42:0;;;-1:-1:-1;;280160:42:0;;;;;;;;;280141:8;;:18;:62::i;:::-;280118:85;-1:-1:-1;280304:23:0;280330:43;-1:-1:-1;;;;;280338:12:0;280330:34;280118:85;280330:34;:43::i;:::-;280304:69;;280940:10;:17;280961:2;280940:23;;:73;;;;280990:23;:8;:21;:23::i;:::-;280967:46;;:19;280975:10;280967:19;:::i;:::-;:46;;280940:73;280936:107;;;281022:21;;;;;;;;;;;;;;280936:107;-1:-1:-1;281060:4:0;;279813:1258;-1:-1:-1;;;;;;279813:1258:0:o;281333:713::-;281529:4;281631:13;281616:28;;:11;:28;;;281612:46;;-1:-1:-1;281653:5:0;281646:12;;281612:46;281771:10;281785:1;281771:15;281767:33;;-1:-1:-1;281795:5:0;281788:12;;281767:33;281832:5;-1:-1:-1;;;;;281817:33:0;;281881:14;281919:8;281953:10;281990:38;282006:11;282019:8;281990:15;:38::i;:::-;281817:222;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;281810:229;281333:713;-1:-1:-1;;;;;;281333:713:0:o;193298:209::-;192212:1;193478:7;:22;193298:209::o;225554:100::-;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;159320:69:0;225621:26:::1;:24;:26::i;192293:111::-:0;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;159320:69:0;192363:34:::1;:32;:34::i;287554:1088::-:0;287789:21;287813:27;;;:14;:27;;;;;;287676:24;;-1:-1:-1;;;;;287813:27:0;;287850:66;;-1:-1:-1;287899:17:0;;;;287850:66;288003:16;288022:6;288029:8;:18;;;288022:26;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;288091:19;;;:9;:19;;;;;;:31;288022:26;;-1:-1:-1;288081:42:0;;288091:31;;288081:9;:42::i;:::-;-1:-1:-1;288323:15:0;;288480:19;;;;;288607:17;;;;;208044:147;;24824:3:1;24820:16;;;24729:66;24816:25;;;208044:147:0;;;24804:38:1;288366:11:0;24875:16:1;;;24871:25;;;24858:11;;;24851:46;24913:11;;;24906:27;;;24949:12;;;24942:28;;;25008:3;25004:16;;;;25022:66;25000:89;24986:12;;;24979:111;25209:15;;;25109:66;25205:24;;;25191:12;;;25184:46;25264:15;;;25260:24;;25246:12;;;25239:46;25320:15;;;25316:24;25301:13;;;25294:47;208044:147:0;;;;;;;;;25357:13:1;;;;208044:147:0;;25209:15:1;;-1:-1:-1;288275:360:0;207728:470;208339:129;208407:7;208433:28;208447:13;:7;:11;:13::i;:::-;208433;:28::i;283348:1705::-;283410:4;283501:11;283479:33;;:18;:4;:16;:18::i;:::-;:33;;;283475:74;;283521:28;;;;;;;;;;;;;;283475:74;283559:19;283581:18;:4;:16;:18::i;:::-;283609:27;283639:25;;;:12;:25;;;;;;;;283609:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;283609:55:0;;;;;283639:25;;-1:-1:-1;283753:20:0;;283749:38;;-1:-1:-1;283782:5:0;;283348:1705;-1:-1:-1;;;283348:1705:0:o;283749:38::-;283876:15;;283859:32;;:13;:4;:11;:13::i;:::-;:32;;;;:76;;;;283916:8;:19;;;283895:40;;:17;:4;:15;:17::i;:::-;:40;;;;283859:76;283855:94;;;-1:-1:-1;283944:5:0;;283348:1705;-1:-1:-1;;;283348:1705:0:o;283855:94::-;284044:16;284063:19;:4;:17;:19::i;:::-;284093:17;284125:19;;;:9;:19;;;;;:31;284044:38;;-1:-1:-1;284093:17:0;284115:42;;284125:31;;284115:9;:42::i;:::-;284092:65;;;284183:6;284190:8;:18;;;284183:26;;;;;;;;;;:::i;:::-;;;;;;;;;284171:8;:38;;:71;;;;284233:9;-1:-1:-1;;;;;284213:29:0;:16;:4;:14;:16::i;:::-;-1:-1:-1;;;;;284213:29:0;;;284171:71;284167:89;;;-1:-1:-1;284251:5:0;;283348:1705;-1:-1:-1;;;;;283348:1705:0:o;284167:89::-;284330:21;284354:27;;;:14;:27;;;;;;-1:-1:-1;;;;;284354:27:0;;284391:656;;284541:8;:17;;;-1:-1:-1;;;;;284517:41:0;:20;:4;:18;:20::i;:::-;-1:-1:-1;;;;;284517:41:0;;:86;;;;;284586:8;:17;;;-1:-1:-1;;;;;284562:41:0;:20;:4;:18;:20::i;:::-;-1:-1:-1;;;;;284562:41:0;;284517:86;284510:93;283348:1705;-1:-1:-1;;;;;;;283348:1705:0:o;284391:656::-;284847:21;284871:20;:4;:18;:20::i;:::-;284847:44;;284936:13;-1:-1:-1;;;;;284912:37:0;:20;:4;:18;:20::i;:::-;-1:-1:-1;;;;;284912:37:0;;:124;;;;-1:-1:-1;;;;;;284970:27:0;;;;:65;;;285018:8;:17;;;-1:-1:-1;;;;;285001:34:0;:13;-1:-1:-1;;;;;285001:34:0;;284970:65;284905:131;283348:1705;-1:-1:-1;;;;;;;;283348:1705:0:o;110370:569::-;110458:10;;110424:7;;110884:4;110875:14;;110915:17;110875:14;110458:10;110915:5;:17::i;200773:215::-;200840:11;200868:22;200882:7;200868:13;:22::i;:::-;200863:60;;200899:24;;;;;;;;;;;;;;122950:538;123041:7;;123083:29;:7;123097:6;123105;123083:13;:29::i;:::-;123453:2;:11;;;123469:1;123452:18;123426:45;;-1:-1:-1;;122950:538:0;;;;;:::o;202531:149::-;202589:7;202615:58;202589:7;202669:2;202615:3;:12;153149:216;203591:231;203652:6;203750:64;199169:2;203811:1;203750:3;:12;153149:216;203977:226;204036:6;204134:61;199221:2;204192:1;204134:3;:12;153149:216;121258:1334;121345:14;121375:6;121385:1;121375:11;121371:59;;-1:-1:-1;121417:1:0;121402:17;;121371:59;121516:2;121507:6;:11;121503:65;;;121541:16;;;;;;;;;;;;;;121503:65;114663:17;114637:43;;121647:15;121656:6;121647;:15;:::i;:::-;:31;121643:82;;;121701:13;;;;;;;;;;;;;;121643:82;121764:1;121754:11;;;121734:17;121804:13;:7;114296:3;114269:30;;114110:196;121804:13;122551:17;;;122545:24;122262:66;122243:17;;;;;122239:90;;;;122541:35;;121258:1334;-1:-1:-1;;;;121258:1334:0:o;68289:187::-;68345:6;68380:16;68371:25;;;68363:76;;;;-1:-1:-1;;;68363:76:0;;23688:2:1;68363:76:0;;;23670:21:1;23727:2;23707:18;;;23700:30;23766:34;23746:18;;;23739:62;23837:8;23817:18;;;23810:36;23863:19;;68363:76:0;23486:402:1;224382:187:0;224474:6;;;-1:-1:-1;;;;;224490:17:0;;;;;;;;;;;224522:40;;224474:6;;;224490:17;224474:6;;224522:40;;224455:16;;224522:40;224445:124;224382:187;:::o;257752:195::-;257815:7;257839:18;257849:7;257839:9;:18::i;:::-;257834:52;;257866:20;;;;;;;;;;;;;;150889:328;150954:6;150408:21;150379:51;148940:6;153936:26;;;150379:51;;;151015:52;;151051:16;;;;;;;;;;;;;;240685:255;240747:7;240862:71;240883:25;:18;:11;:16;:18::i;:::-;151371:20;151527:17;;;151643:2;151630:16;;;151319:343;240883:25;240910:22;:11;:20;:22::i;130845:287::-;130926:14;130956:23;;:51;;;;-1:-1:-1;130983:24:0;;130956:51;130952:174;;;-1:-1:-1;131030:1:0;131023:8;;130952:174;131079:35;;;;;;24050:19:1;;;24085:12;;;24078:28;;;24122:12;;131079:35:0;;;;;;;;;;;;131069:46;;;;;;131062:53;;;;187136:200;187200:8;187225:19;187236:7;187225:10;:19::i;:::-;187220:54;;187253:21;;;;;;;;;;;;;;188158:115;188214:7;188240:26;:8;:24;:26::i;:17::-;:24;:26::i;128573:900::-;128813:12;;128708:13;;128839:17;;;128835:48;;;128865:18;;;;;;;;;;;;;;128835:48;128901:4;128893:12;;129070:9;129065:189;129089:8;129085:1;:12;129065:189;;;129203:36;129213:5;129220;129226:1;129220:8;;;;;;;;:::i;:::-;;;;;;;129230:5;129237:1;129203:9;:36::i;:::-;129195:44;-1:-1:-1;129099:3:0;;129065:189;;;-1:-1:-1;129351:8:0;129334:123;129365:6;129361:1;:10;129334:123;;;129404:38;129414:5;129429:1;129433:5;129440:1;129404:9;:38::i;:::-;129396:46;-1:-1:-1;129373:3:0;;129334:123;;;;128727:746;128573:900;;;;;;:::o;251357:998::-;251508:7;251865:24;251888:1;251865:24;;;;251991:25;251973:44;;251969:74;;252026:17;;;;;;;;;;;;;;251969:74;252053:16;252072:37;252090:10;252102:6;252072:17;:37::i;:::-;252053:56;;252270:78;252291:13;252306:8;252316:9;24640:1;252270:20;:78::i;261135:127::-;261189:7;261215:40;256534:29;25896:2;261189:7;256534:29;:::i;:::-;261215:7;;:17;:40::i;240129:241::-;240192:4;25991:2;238223:30;26088:2;238173;238223:30;:::i;:::-;238301:31;;;;:::i;:::-;114663:17;114637:43;;240273:31;;;240129:241;-1:-1:-1;;240129:241:0:o;242302:203::-;242367:7;242393:105;242416:80;238223:30;26088:2;238173;238223:30;:::i;:::-;25991:2;242416:11;:20;153149:216;242043:166;242110:7;242136:66;238173:2;242198;242136:11;:20;153149:216;242602:154;242667:7;242693:56;25991:2;238223:30;26088:2;238173;238223:30;:::i;:::-;238301:31;;;;:::i;242693:20::-;:30;;:56::i;111477:1041::-;111723:4;111717:11;;111853:34;111867:7;111882:4;111876:10;;111853:13;:34::i;:::-;-1:-1:-1;114663:17:0;114637:43;;112099:12;115495:2;115479:18;;-1:-1:-1;;115863:20:0;112395;;112417:4;112391:31;112385:4;112378:45;-1:-1:-1;112485:17:0;;111477:1041;;-1:-1:-1;111477:1041:0:o;33799:625::-;33928:12;34017:9;-1:-1:-1;;;;;34017:21:0;;34042:1;34017:26;34013:44;;-1:-1:-1;34052:5:0;34045:12;;34013:44;34406:1;34403;34393:7;34387:14;34380:4;34371:7;34367:18;34357:8;34346:9;34336:8;34331:77;34320:88;33799:625;-1:-1:-1;;;;;33799:625:0:o;186094:610::-;186176:12;186271:25;186282:6;:13;190414:2;190405:11;:16;;190277:151;186271:25;186266:66;;186305:27;;;;;;;;;;;;;;186266:66;186367:16;;;186381:1;186367:16;;;;;;;;;186342:22;;186367:16;;;;;;;;;;-1:-1:-1;186367:16:0;186342:41;;186447:47;186464:23;:8;:21;:23::i;:::-;186447:41;;24296:66:1;24284:79;;;186447:41:0;;;24272:92:1;24380:11;;186447:41:0;;;;;;;;;;;;:45;:47::i;:::-;186436:5;186442:1;186436:8;;;;;;;;:::i;:::-;;;;;;:58;;;;;186560:12;:6;:10;:12::i;:::-;186549:5;186555:1;186549:8;;;;;;;;:::i;:::-;;;;;;:23;;;;;186638:20;:8;:18;:20::i;:::-;186627:5;186633:1;186627:8;;;;;;;;:::i;:::-;;;;;;:31;;;;;186675:22;186691:5;186675:15;:22::i;47865:185::-;47940:12;47971:72;47993:6;48001:4;48007:1;47971:72;;;;;;;;;;;;;;;;;:21;:72::i;189325:255::-;189389:6;189474:8;189507:65;189474:8;189389:6;182036:1;189507:13;:65::i;222820:111::-;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;159320:69:0;222892:32:::1;194999:10:::0;222892:18:::1;:32::i;192410:109::-:0;159328:13;;;;;;;159320:69;;;;-1:-1:-1;;;159320:69:0;;23146:2:1;159320:69:0;;;23128:21:1;23185:2;23165:18;;;23158:30;23224:34;23204:18;;;23197:62;23295:13;23275:18;;;23268:41;23326:19;;159320:69:0;22944:407:1;208610:195:0;208673:7;208697:18;208707:7;208697:9;:18::i;:::-;208692:52;;208724:20;;;;;;;;;;;;;;210856:234;210917:6;211015:67;206365:1;;211015:7;:16;153149:216;211151:159;211212:7;211238:65;206419:1;211299:2;211238:7;:16;153149:216;210574:224;210630:6;210728:62;210630:6;210787:1;210728:7;:16;153149:216;211593:236;211653:5;211754:67;206528:2;211818:1;211754:7;:16;153149:216;211372:161;211434:7;211460:66;206474:2;211522;211460:7;:16;153149:216;211896:150;211955:7;211981:58;206581:2;211981:7;:16;:29;;:58::i;212109:158::-;212172:7;212198:62;206638:2;212198:7;:16;153149:216;212330:158;212393:7;212419:62;206695:3;212419:7;:16;153149:216;109490:540;109556:7;;109590:11;109597:4;109590;:11;:::i;:::-;109575:26;;109869:4;109863:11;109857:4;109854:21;109851:38;;;-1:-1:-1;109886:1:0;109851:38;109912:4;109920:1;109912:9;109908:66;;109944:19;;;;;;;;;;;;;;109908:66;124760:3;124752:11;;;124751:20;;109990:33;124427:352;201060:128;201123:4;24980:2;114663:17;114637:43;;201146:13;:35;;201060:128;-1:-1:-1;;201060:128:0:o;258030:803::-;258089:4;114663:17;114637:43;;256534:29;25896:2;258089:4;256534:29;:::i;:::-;258198:6;:20;258194:38;;;-1:-1:-1;258227:5:0;;258030:803;-1:-1:-1;;258030:803:0:o;258194:38::-;258280:20;258303:16;258311:7;258303;:16::i;:::-;258280:39;-1:-1:-1;150408:21:0;150379:51;148940:6;153936:26;;;150379:51;;;258329;;-1:-1:-1;258375:5:0;;258030:803;-1:-1:-1;;;258030:803:0:o;258329:51::-;258550:16;258505:41;:34;258526:12;258505:20;:34::i;:::-;:39;;;:41::i;:::-;:61;;;;;;;;:::i;:::-;;258501:326;;258646:30;:14;258652:7;258646:5;:14::i;:::-;:28;:30::i;258501:326::-;258789:27;:14;258795:7;258789:5;:14::i;:::-;:25;:27::i;241031:163::-;241097:7;241123:64;:55;238121:2;241123:11;:20;153149:216;187496:362;187556:4;114663:17;114637:43;;182036:1;187677:24;;187673:42;;;-1:-1:-1;187710:5:0;;187496:362;-1:-1:-1;;187496:362:0:o;187673:42::-;187815:36;187826:24;182036:1;187826:6;:24;:::i;:::-;190414:2;190405:11;:16;;190277:151;116401:292;116457:14;116483:12;116498:13;:7;114296:3;114269:30;;114110:196;116498:13;114663:17;114637:43;;;;116656:21;;;;;-1:-1:-1;;116401:292:0:o;129855:526::-;129991:14;130196:1;130169:23;;;130168:29;:34;;130164:211;;130251:24;130261:4;130267:7;130251:9;:24::i;:::-;130244:31;;;;130164:211;130340:24;130350:7;130359:4;130340:9;:24::i;233783:220::-;233855:7;233980:5;233987:7;233963:32;;;;;;;;25536:19:1;;;25593:3;25589:16;25607:66;25585:89;25580:2;25571:12;;25564:111;25700:2;25691:12;;25381:328;233963:32:0;;;;;;;;;;;;;233953:43;;;;;;233946:50;;233783:220;;;;:::o;118524:529::-;118599:7;114663:17;114637:43;;118706:13;;;118702:64;;;118742:13;;;;;;;;;;;;;;118702:64;118978:58;119007:6;118991:13;:7;114296:3;114269:30;;114110:196;118991:13;:22;119028:6;119021:4;:13;118978:5;:58::i;125411:842::-;125750:4;125744:11;125489:7;;114663:17;114637:43;;;114296:3;114269:30;;;;125832:12;;;125828:66;;;125867:16;;;;;;;;;;;;;;125828:66;125903:8;126119:4;126111:6;126105:4;126097:6;126091:4;126084:5;126073:51;126066:58;;126148:3;126143:37;;126160:20;;;;;;;;;;;;;;126143:37;124760:3;124752:11;;;124751:20;;126197:49;124427:352;189659:225;189720:7;189806:8;189832:45;189806:8;182036:1;189832:17;:45::i;112738:892::-;112993:4;112987:11;;112830;113158:33;113170:8;113186:4;113180:10;;113158:11;:33::i;:::-;114663:17;114637:43;115495:2;115479:18;;-1:-1:-1;;115863:20:0;113507;;113529:4;113503:31;113497:4;113490:45;113597:17;;;-1:-1:-1;112738:892:0;;-1:-1:-1;112738:892:0:o;49329:446::-;49494:12;49551:5;49526:21;:30;;49518:81;;;;-1:-1:-1;;;49518:81:0;;25916:2:1;49518:81:0;;;25898:21:1;25955:2;25935:18;;;25928:30;25994:34;25974:18;;;25967:62;26065:8;26045:18;;;26038:36;26091:19;;49518:81:0;25714:402:1;49518:81:0;49610:12;49624:23;49651:6;-1:-1:-1;;;;;49651:11:0;49670:5;49677:4;49651:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49609:73;;;;49699:69;49726:6;49734:7;49743:10;49755:12;49699:26;:69::i;208873:152::-;208932:4;25250:3;114663:17;114637:43;;208987:13;114479:208;123751:225;123829:7;123938:29;:7;123956:6;123964:2;123938:17;:29::i;260829:154::-;260885:7;260911:65;:7;260885;25896:2;260911:17;:65::i;126788:1003::-;127058:4;127052:11;126876:7;;127140:14;;;127136:68;;;127177:16;;;;;;;;;;;;;;127136:68;127323:14;127356:9;127351:364;127375:8;:15;127371:1;:19;127351:364;;;127407:15;127425:8;127434:1;127425:11;;;;;;;;:::i;:::-;;;;;;;127407:29;;127587:41;127601:7;127621:6;127610:8;:17;127587:13;:41::i;:::-;-1:-1:-1;114663:17:0;114637:43;127646:23;;;;;127687:3;;127351:364;;;-1:-1:-1;124760:3:0;124752:11;;;124751:20;;127731:53;124427:352;51835:628;52015:12;52043:7;52039:418;;;52070:10;:17;52091:1;52070:22;52066:286;;-1:-1:-1;;;;;90357:19:0;;;52277:60;;;;-1:-1:-1;;;52277:60:0;;26615:2:1;52277:60:0;;;26597:21:1;26654:2;26634:18;;;26627:30;26693:31;26673:18;;;26666:59;26742:18;;52277:60:0;26413:353:1;52277:60:0;-1:-1:-1;52372:10:0;52365:17;;52039:418;52413:33;52421:10;52433:12;53144:17;;:21;53140:379;;53372:10;53366:17;53428:15;53415:10;53411:2;53407:19;53400:44;53140:379;53495:12;53488:20;;-1:-1:-1;;;53488:20:0;;;;;;;;:::i;14:154:1:-;-1:-1:-1;;;;;93:5:1;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:250::-;1521:1;1531:113;1545:6;1542:1;1539:13;1531:113;;;1621:11;;;1615:18;1602:11;;;1595:39;1567:2;1560:10;1531:113;;;-1:-1:-1;;1678:1:1;1660:16;;1653:27;1436:250::o;1691:329::-;1732:3;1770:5;1764:12;1797:6;1792:3;1785:19;1813:76;1882:6;1875:4;1870:3;1866:14;1859:4;1852:5;1848:16;1813:76;:::i;:::-;1934:2;1922:15;-1:-1:-1;;1918:88:1;1909:98;;;;2009:4;1905:109;;1691:329;-1:-1:-1;;1691:329:1:o;2025:377::-;2218:2;2207:9;2200:21;2181:4;2244:44;2284:2;2273:9;2269:18;2261:6;2244:44;:::i;:::-;2336:9;2328:6;2324:22;2319:2;2308:9;2304:18;2297:50;2364:32;2389:6;2381;2364:32;:::i;2407:379::-;-1:-1:-1;;;;;2658:55:1;;2640:74;;2627:3;2612:19;;2723:57;2776:2;2761:18;;2753:6;2723:57;:::i;2791:121::-;2876:10;2869:5;2865:22;2858:5;2855:33;2845:61;;2902:1;2899;2892:12;2917:245;2975:6;3028:2;3016:9;3007:7;3003:23;2999:32;2996:52;;;3044:1;3041;3034:12;2996:52;3083:9;3070:23;3102:30;3126:5;3102:30;:::i;3364:184::-;3416:77;3413:1;3406:88;3513:4;3510:1;3503:15;3537:4;3534:1;3527:15;3553:334;3624:2;3618:9;3680:2;3670:13;;-1:-1:-1;;3666:86:1;3654:99;;3783:18;3768:34;;3804:22;;;3765:62;3762:88;;;3830:18;;:::i;:::-;3866:2;3859:22;3553:334;;-1:-1:-1;3553:334:1:o;3892:245::-;3940:4;3973:18;3965:6;3962:30;3959:56;;;3995:18;;:::i;:::-;-1:-1:-1;4052:2:1;4040:15;-1:-1:-1;;4036:88:1;4126:4;4032:99;;3892:245::o;4142:462::-;4184:5;4237:3;4230:4;4222:6;4218:17;4214:27;4204:55;;4255:1;4252;4245:12;4204:55;4291:6;4278:20;4322:48;4338:31;4366:2;4338:31;:::i;:::-;4322:48;:::i;:::-;4395:2;4386:7;4379:19;4441:3;4434:4;4429:2;4421:6;4417:15;4413:26;4410:35;4407:55;;;4458:1;4455;4448:12;4407:55;4523:2;4516:4;4508:6;4504:17;4497:4;4488:7;4484:18;4471:55;4571:1;4546:16;;;4564:4;4542:27;4535:38;;;;4550:7;4142:462;-1:-1:-1;;;4142:462:1:o;4609:1651::-;4766:6;4774;4782;4790;4798;4851:3;4839:9;4830:7;4826:23;4822:33;4819:53;;;4868:1;4865;4858:12;4819:53;4907:9;4894:23;4926:30;4950:5;4926:30;:::i;:::-;4975:5;-1:-1:-1;4999:2:1;5033:18;;;5020:32;;-1:-1:-1;5103:2:1;5088:18;;5075:32;5126:18;5156:14;;;5153:34;;;5183:1;5180;5173:12;5153:34;5206:49;5247:7;5238:6;5227:9;5223:22;5206:49;:::i;:::-;5196:59;;5302:2;5291:9;5287:18;5274:32;5264:42;;5359:3;5348:9;5344:19;5331:33;5315:49;;5389:2;5379:8;5376:16;5373:36;;;5405:1;5402;5395:12;5373:36;5443:8;5432:9;5428:24;5418:34;;5490:7;5483:4;5479:2;5475:13;5471:27;5461:55;;5512:1;5509;5502:12;5461:55;5548:2;5535:16;5570:2;5566;5563:10;5560:36;;;5576:18;;:::i;:::-;5622:2;5619:1;5615:10;5605:20;;5645:28;5669:2;5665;5661:11;5645:28;:::i;:::-;5707:15;;;5777:11;;;5773:20;;;5738:12;;;;5805:19;;;5802:39;;;5837:1;5834;5827:12;5802:39;5861:11;;;;5881:349;5897:6;5892:3;5889:15;5881:349;;;5979:3;5966:17;5951:32;;6031:34;6022:7;6018:48;6009:7;6006:61;5996:159;;6109:1;6138:2;6134;6127:14;5996:159;6168:20;;;5914:12;;;;6208;;;;5881:349;;;6249:5;6239:15;;;;;;;;4609:1651;;;;;;;;:::o;6642:118::-;6728:1;6721:5;6718:12;6708:46;;6734:18;;:::i;6765:245::-;6915:2;6900:18;;6927:43;6963:6;6927:43;:::i;:::-;6979:25;;;6765:245;:::o;7581:219::-;7730:2;7719:9;7712:21;7693:4;7750:44;7790:2;7779:9;7775:18;7767:6;7750:44;:::i;7987:380::-;8063:8;8073:6;8127:3;8120:4;8112:6;8108:17;8104:27;8094:55;;8145:1;8142;8135:12;8094:55;-1:-1:-1;8168:20:1;;8211:18;8200:30;;8197:50;;;8243:1;8240;8233:12;8197:50;8280:4;8272:6;8268:17;8256:29;;8340:3;8333:4;8323:6;8320:1;8316:14;8308:6;8304:27;8300:38;8297:47;8294:67;;;8357:1;8354;8347:12;8294:67;7987:380;;;;;:::o;8372:474::-;8482:6;8490;8543:2;8531:9;8522:7;8518:23;8514:32;8511:52;;;8559:1;8556;8549:12;8511:52;8599:9;8586:23;8632:18;8624:6;8621:30;8618:50;;;8664:1;8661;8654:12;8618:50;8703:83;8778:7;8769:6;8758:9;8754:22;8703:83;:::i;:::-;8805:8;;8677:109;;-1:-1:-1;8372:474:1;-1:-1:-1;;;;8372:474:1:o;8851:1099::-;9041:4;9070:2;9110;9099:9;9095:18;9140:2;9129:9;9122:21;9163:6;9198;9192:13;9229:6;9221;9214:22;9255:2;9245:12;;9288:2;9277:9;9273:18;9266:25;;9350:2;9340:6;9337:1;9333:14;9322:9;9318:30;9314:39;9388:2;9380:6;9376:15;9409:1;9419:502;9433:6;9430:1;9427:13;9419:502;;;9498:22;;;9522:66;9494:95;9482:108;;9613:13;;9668:9;;9661:17;9654:25;9639:41;;9719:11;;9713:18;9751:15;;;9744:27;;;9794:47;9825:15;;;9713:18;9794:47;:::i;:::-;9899:12;;;;9784:57;-1:-1:-1;;9864:15:1;;;;9455:1;9448:9;9419:502;;;-1:-1:-1;9938:6:1;;8851:1099;-1:-1:-1;;;;;;;;8851:1099:1:o;9955:384::-;10021:6;10029;10082:2;10070:9;10061:7;10057:23;10053:32;10050:52;;;10098:1;10095;10088:12;10050:52;10137:9;10124:23;10156:30;10180:5;10156:30;:::i;:::-;10205:5;-1:-1:-1;10262:2:1;10247:18;;10234:32;10275;10234;10275;:::i;:::-;10326:7;10316:17;;;9955:384;;;;;:::o;10575:1320::-;10730:6;10738;10746;10754;10762;10770;10778;10831:3;10819:9;10810:7;10806:23;10802:33;10799:53;;;10848:1;10845;10838:12;10799:53;10888:9;10875:23;10917:18;10958:2;10950:6;10947:14;10944:34;;;10974:1;10971;10964:12;10944:34;10997:49;11038:7;11029:6;11018:9;11014:22;10997:49;:::i;:::-;10987:59;;11099:2;11088:9;11084:18;11071:32;11055:48;;11128:2;11118:8;11115:16;11112:36;;;11144:1;11141;11134:12;11112:36;11183:85;11260:7;11249:8;11238:9;11234:24;11183:85;:::i;:::-;11287:8;;-1:-1:-1;11157:111:1;-1:-1:-1;11375:2:1;11360:18;;11347:32;;-1:-1:-1;11391:16:1;;;11388:36;;;11420:1;11417;11410:12;11388:36;11459:85;11536:7;11525:8;11514:9;11510:24;11459:85;:::i;:::-;11563:8;;-1:-1:-1;11433:111:1;-1:-1:-1;11648:2:1;11633:18;;11620:32;;-1:-1:-1;11692:4:1;11681:16;;11671:27;;11661:55;;11712:1;11709;11702:12;11661:55;11735:5;;-1:-1:-1;11792:3:1;11777:19;;11764:33;;11828:16;;;11816:29;;11806:57;;11859:1;11856;11849:12;11806:57;;11882:7;11872:17;;;10575:1320;;;;;;;;;;:::o;12435:531::-;12653:13;;12631:2;12616:18;;;12675:39;12653:13;12675:39;:::i;:::-;12741:2;12730:9;12723:21;;12791:4;12783:6;12779:17;12773:24;12816:12;12884:2;12870:12;12866:21;12859:4;12848:9;12844:20;12837:51;12956:2;12948:4;12940:6;12936:17;12930:24;12926:33;12919:4;12908:9;12904:20;12897:63;;;12435:531;;;;:::o;12971:320::-;13039:6;13092:2;13080:9;13071:7;13067:23;13063:32;13060:52;;;13108:1;13105;13098:12;13060:52;13148:9;13135:23;13181:18;13173:6;13170:30;13167:50;;;13213:1;13210;13203:12;13167:50;13236:49;13277:7;13268:6;13257:9;13253:22;13236:49;:::i;13296:184::-;13348:77;13345:1;13338:88;13445:4;13442:1;13435:15;13469:4;13466:1;13459:15;13485:647;13564:6;13617:2;13605:9;13596:7;13592:23;13588:32;13585:52;;;13633:1;13630;13623:12;13585:52;13666:9;13660:16;13699:18;13691:6;13688:30;13685:50;;;13731:1;13728;13721:12;13685:50;13754:22;;13807:4;13799:13;;13795:27;-1:-1:-1;13785:55:1;;13836:1;13833;13826:12;13785:55;13865:2;13859:9;13890:48;13906:31;13934:2;13906:31;:::i;13890:48::-;13961:2;13954:5;13947:17;14001:7;13996:2;13991;13987;13983:11;13979:20;13976:33;13973:53;;;14022:1;14019;14012:12;13973:53;14035:67;14099:2;14094;14087:5;14083:14;14078:2;14074;14070:11;14035:67;:::i;14137:184::-;14207:6;14260:2;14248:9;14239:7;14235:23;14231:32;14228:52;;;14276:1;14273;14266:12;14228:52;-1:-1:-1;14299:16:1;;14137:184;-1:-1:-1;14137:184:1:o;14326:380::-;14416:4;14474:11;14461:25;14564:66;14553:8;14537:14;14533:29;14529:102;14509:18;14505:127;14495:155;;14646:1;14643;14636:12;14495:155;14667:33;;;;;14326:380;-1:-1:-1;;14326:380:1:o;14711:580::-;14788:4;14794:6;14854:11;14841:25;14944:66;14933:8;14917:14;14913:29;14909:102;14889:18;14885:127;14875:155;;15026:1;15023;15016:12;14875:155;15053:33;;15105:20;;;-1:-1:-1;15148:18:1;15137:30;;15134:50;;;15180:1;15177;15170:12;15134:50;15213:4;15201:17;;-1:-1:-1;15244:14:1;15240:27;;;15230:38;;15227:58;;;15281:1;15278;15271:12;15296:271;15479:6;15471;15466:3;15453:33;15435:3;15505:16;;15530:13;;;15505:16;15296:271;-1:-1:-1;15296:271:1:o;15982:184::-;16034:77;16031:1;16024:88;16131:4;16128:1;16121:15;16155:4;16152:1;16145:15;16171:128;16238:9;;;16259:11;;;16256:37;;;16273:18;;:::i;17171:174::-;17238:12;17270:10;;;17282;;;17266:27;;17305:11;;;17302:37;;;17319:18;;:::i;:::-;17302:37;17171:174;;;;:::o;17757:758::-;17826:5;17874:4;17862:9;17857:3;17853:19;17849:30;17846:50;;;17892:1;17889;17882:12;17846:50;17925:2;17919:9;17967:4;17959:6;17955:17;18038:6;18026:10;18023:22;18002:18;17990:10;17987:34;17984:62;17981:88;;;18049:18;;:::i;:::-;18089:10;18085:2;18078:22;;18118:6;18109:15;;18154:9;18148:16;18195:1;18186:7;18183:14;18173:42;;18211:1;18208;18201:12;18173:42;18224:23;;18292:2;18277:18;;18271:25;18305:32;18271:25;18305:32;:::i;:::-;18365:2;18353:15;;18346:32;18423:2;18408:18;;18402:25;18436:32;18402:25;18436:32;:::i;:::-;18496:2;18484:15;;;;18477:32;17757:758;;-1:-1:-1;;17757:758:1:o;18520:257::-;18619:6;18672:2;18660:9;18651:7;18647:23;18643:32;18640:52;;;18688:1;18685;18678:12;18640:52;18711:60;18763:7;18752:9;18711:60;:::i;19429:386::-;19537:6;19545;19598:3;19586:9;19577:7;19573:23;19569:33;19566:53;;;19615:1;19612;19605:12;19566:53;19647:9;19641:16;19666:31;19691:5;19666:31;:::i;:::-;19716:5;-1:-1:-1;19740:69:1;19801:7;19796:2;19781:18;;19740:69;:::i;:::-;19730:79;;19429:386;;;;;:::o;19820:195::-;19859:3;19890:66;19883:5;19880:77;19877:103;;19960:18;;:::i;:::-;-1:-1:-1;20007:1:1;19996:13;;19820:195::o;20741:175::-;20809:10;20852;;;20840;;;20836:27;;20875:12;;;20872:38;;;20890:18;;:::i;20921:626::-;21165:4;21194:10;21243:2;21235:6;21231:15;21220:9;21213:34;21295:2;21287:6;21283:15;21278:2;21267:9;21263:18;21256:43;21335:6;21330:2;21319:9;21315:18;21308:34;21378:6;21373:2;21362:9;21358:18;21351:34;21434:2;21426:6;21422:15;21416:3;21405:9;21401:19;21394:44;;21475:3;21469;21458:9;21454:19;21447:32;21496:45;21536:3;21525:9;21521:19;21513:6;21496:45;:::i;21820:357::-;21938:12;;21985:4;21974:16;;;21968:23;;21938:12;22003:16;;22000:171;;;22093:66;22077:4;22073:17;;;;22070:1;22066:25;22062:98;22051:110;;21820:357;-1:-1:-1;21820:357:1:o;22182:475::-;22372:4;22401:10;22450:2;22442:6;22438:15;22427:9;22420:34;22502:2;22494:6;22490:15;22485:2;22474:9;22470:18;22463:43;;22542:6;22537:2;22526:9;22522:18;22515:34;22585:3;22580:2;22569:9;22565:18;22558:31;22606:45;22646:3;22635:9;22631:19;22623:6;22606:45;:::i;22662:277::-;22729:6;22782:2;22770:9;22761:7;22757:23;22753:32;22750:52;;;22798:1;22795;22788:12;22750:52;22830:9;22824:16;22883:5;22876:13;22869:21;22862:5;22859:32;22849:60;;22905:1;22902;22895:12;23356:125;23421:9;;;23442:10;;;23439:36;;;23455:18;;:::i;26121:287::-;26250:3;26288:6;26282:13;26304:66;26363:6;26358:3;26351:4;26343:6;26339:17;26304:66;:::i","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"agentManager_","type":"address"},{"internalType":"address","name":"inbox_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExecuted","type":"error"},{"inputs":[],"name":"AlreadyFailed","type":"error"},{"inputs":[],"name":"CallerNotAgentManager","type":"error"},{"inputs":[],"name":"CallerNotInbox","type":"error"},{"inputs":[],"name":"DisputeTimeoutNotOver","type":"error"},{"inputs":[],"name":"DuplicatedSnapshotRoot","type":"error"},{"inputs":[],"name":"FlagOutOfRange","type":"error"},{"inputs":[],"name":"GasLimitTooLow","type":"error"},{"inputs":[],"name":"GasSuppliedTooLow","type":"error"},{"inputs":[],"name":"IncorrectDestinationDomain","type":"error"},{"inputs":[],"name":"IncorrectMagicValue","type":"error"},{"inputs":[],"name":"IncorrectOriginDomain","type":"error"},{"inputs":[],"name":"IncorrectSnapshotRoot","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"MessageOptimisticPeriod","type":"error"},{"inputs":[],"name":"NotaryInDispute","type":"error"},{"inputs":[],"name":"OccupiedMemory","type":"error"},{"inputs":[],"name":"OutdatedNonce","type":"error"},{"inputs":[],"name":"PrecompileOutOfGas","type":"error"},{"inputs":[],"name":"TreeHeightTooLow","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedAttestation","type":"error"},{"inputs":[],"name":"UnformattedBaseMessage","type":"error"},{"inputs":[],"name":"UnformattedCallData","type":"error"},{"inputs":[],"name":"UnformattedCallDataPrefix","type":"error"},{"inputs":[],"name":"UnformattedMessage","type":"error"},{"inputs":[],"name":"UnformattedReceipt","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"agentRoot","type":"bytes32"}],"name":"AgentRootAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"remoteDomain","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"Executed","type":"event"},{"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":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"paddedTips","type":"uint256"}],"name":"TipsRecorded","type":"event"},{"inputs":[{"internalType":"uint32","name":"notaryIndex","type":"uint32"},{"internalType":"uint256","name":"sigIndex","type":"uint256"},{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes32","name":"agentRoot","type":"bytes32"},{"internalType":"ChainGas[]","name":"snapGas","type":"uint128[]"}],"name":"acceptAttestation","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"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":"attestationsAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"destStatus","outputs":[{"internalType":"uint40","name":"snapRootTime","type":"uint40"},{"internalType":"uint40","name":"agentRootTime","type":"uint40"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"msgPayload","type":"bytes"},{"internalType":"bytes32[]","name":"originProof","type":"bytes32[]"},{"internalType":"bytes32[]","name":"snapProof","type":"bytes32[]"},{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","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":"getAttestation","outputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"snapRoot","type":"bytes32"}],"name":"getAttestationNonce","outputs":[{"internalType":"uint32","name":"attNonce","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"}],"name":"getGasData","outputs":[{"internalType":"GasData","name":"gasData","type":"uint96"},{"internalType":"uint256","name":"dataMaturity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"agentRoot","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"name":"isValidReceipt","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"lastAttestationNonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"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":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageReceipt","outputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageStatus","outputs":[{"internalType":"enum MessageStatus","name":"status","type":"uint8"}],"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":"nextAgentRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"passAgentRoot","outputs":[{"internalType":"bool","name":"rootPending","type":"bool"}],"stateMutability":"nonpayable","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":{"events":{"Executed(uint32,bytes32,bool)":{"notice":"Emitted when message is executed."},"TipsRecorded(bytes32,uint256)":{"notice":"Emitted when message tips are recorded."}},"kind":"user","methods":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":{"notice":"Accepts an attestation, which local `AgentManager` verified to have been signed by an active Notary for this chain. \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain. - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree. - Messages coming from chains included in the Attestation's snapshot could be proven. - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is in Dispute. \u003e - Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local `AgentManager`."},"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."},"attestationsAmount()":{"notice":"Returns the total amount of Notaries attestations that have been accepted."},"destStatus()":{"notice":"Returns status of Destination contract as far as snapshot/agent roots are concerned"},"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"notice":"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"getAttestation(uint256)":{"notice":"Returns a Notary-signed attestation with a given index. \u003e Index refers to the list of all attestations accepted by this contract."},"getAttestationNonce(bytes32)":{"notice":"Returns attestation nonce for a given snapshot root."},"getGasData(uint32)":{"notice":"Returns the gas data for a given chain from the latest accepted attestation with that chain."},"inbox()":{"notice":"Returns the address of the local Inbox contract, which is treated as the \"source of truth\" for agent-signed statements."},"initialize(bytes32)":{"notice":"Initializes Destination contract: - msg.sender is set as contract owner"},"isValidReceipt(bytes)":{"notice":"Checks the validity of the unsigned message receipt."},"lastAttestationNonce(uint32)":{"notice":"Returns the nonce of the last attestation submitted by a Notary with a given agent index."},"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"},"messageReceipt(bytes32)":{"notice":"Returns a formatted payload with the message receipt."},"messageStatus(bytes32)":{"notice":"Returns message execution status: None/Failed/Success."},"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."},"nextAgentRoot()":{"notice":"Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over."},"openDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened."},"passAgentRoot()":{"notice":"Attempts to pass a quarantined Agent Merkle Root to a local Light Manager."},"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":"Harness for standalone Go tests. Do not use for tests requiring interactions between messaging contracts.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":{"params":{"agentRoot":"Agent Merkle Root from the Attestation","attPayload":"Raw payload with Attestation data","notaryIndex":"Index of Attestation Notary in Agent Merkle Tree","sigIndex":"Index of stored Notary signature","snapGas":"Gas data for each chain in the Attestation's snapshot"},"returns":{"wasAccepted":"     Whether the Attestation was accepted"}},"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)."}},"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"details":"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.","params":{"gasLimit":"Gas limit for message execution","msgPayload":"Raw payload with a formatted message to execute","originProof":"Proof of inclusion of message in the Origin Merkle Tree","snapProof":"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree","stateIndex":"Index of Origin State in the Snapshot"}},"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)"}},"getAttestation(uint256)":{"details":"Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.","params":{"index":"Attestation index"},"returns":{"attPayload":"      Raw payload with Attestation data","attSignature":"    Notary signature for the reported attestation"}},"getAttestationNonce(bytes32)":{"details":"Will return 0 if the root is unknown."},"getGasData(uint32)":{"details":"Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.","params":{"domain":"Domain for the chain"},"returns":{"dataMaturity":"    Gas data age in seconds","gasData":"         Gas data for the chain"}},"isValidReceipt(bytes)":{"details":"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.","params":{"rcptPayload":"Raw payload with Receipt data"},"returns":{"isValid":"         Whether the requested receipt 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)"}},"messageReceipt(bytes32)":{"details":"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.","params":{"messageHash":"Hash of the message payload"},"returns":{"rcptPayload":"            Formatted payload with the message execution receipt"}},"messageStatus(bytes32)":{"params":{"messageHash":"Hash of the message payload"},"returns":{"status":"          Message execution status"}},"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."},"passAgentRoot()":{"details":"Will do nothing, if root optimistic period is not over.","returns":{"rootPending":" Whether there is a pending agent merkle root left"}},"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."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"agentManager_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inbox_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CallerNotAgentManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CallerNotInbox\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputeTimeoutNotOver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicatedSnapshotRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlagOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasSuppliedTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectDestinationDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectMagicValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectOriginDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSnapshotRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageOptimisticPeriod\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotaryInDispute\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OccupiedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutdatedNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrecompileOutOfGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TreeHeightTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedAttestation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedBaseMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedCallData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedCallDataPrefix\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedReceipt\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"}],\"name\":\"AgentRootAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"remoteDomain\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"Executed\",\"type\":\"event\"},{\"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\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"}],\"name\":\"TipsRecorded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"sigIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"},{\"internalType\":\"ChainGas[]\",\"name\":\"snapGas\",\"type\":\"uint128[]\"}],\"name\":\"acceptAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"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\":\"attestationsAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destStatus\",\"outputs\":[{\"internalType\":\"uint40\",\"name\":\"snapRootTime\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"agentRootTime\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"msgPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"originProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"snapProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"getAttestation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"snapRoot\",\"type\":\"bytes32\"}],\"name\":\"getAttestationNonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"}],\"name\":\"getGasData\",\"outputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"dataMaturity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"name\":\"isValidReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"lastAttestationNonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"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\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageReceipt\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageStatus\",\"outputs\":[{\"internalType\":\"enum MessageStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"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\":\"nextAgentRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"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\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passAgentRoot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"rootPending\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"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\":{\"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])\":{\"params\":{\"agentRoot\":\"Agent Merkle Root from the Attestation\",\"attPayload\":\"Raw payload with Attestation data\",\"notaryIndex\":\"Index of Attestation Notary in Agent Merkle Tree\",\"sigIndex\":\"Index of stored Notary signature\",\"snapGas\":\"Gas data for each chain in the Attestation's snapshot\"},\"returns\":{\"wasAccepted\":\"     Whether the Attestation was accepted\"}},\"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).\"}},\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"details\":\"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\",\"params\":{\"gasLimit\":\"Gas limit for message execution\",\"msgPayload\":\"Raw payload with a formatted message to execute\",\"originProof\":\"Proof of inclusion of message in the Origin Merkle Tree\",\"snapProof\":\"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\",\"stateIndex\":\"Index of Origin State in the Snapshot\"}},\"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)\"}},\"getAttestation(uint256)\":{\"details\":\"Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.\",\"params\":{\"index\":\"Attestation index\"},\"returns\":{\"attPayload\":\"      Raw payload with Attestation data\",\"attSignature\":\"    Notary signature for the reported attestation\"}},\"getAttestationNonce(bytes32)\":{\"details\":\"Will return 0 if the root is unknown.\"},\"getGasData(uint32)\":{\"details\":\"Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.\",\"params\":{\"domain\":\"Domain for the chain\"},\"returns\":{\"dataMaturity\":\"    Gas data age in seconds\",\"gasData\":\"         Gas data for the chain\"}},\"isValidReceipt(bytes)\":{\"details\":\"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.\",\"params\":{\"rcptPayload\":\"Raw payload with Receipt data\"},\"returns\":{\"isValid\":\"         Whether the requested receipt 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)\"}},\"messageReceipt(bytes32)\":{\"details\":\"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\",\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"rcptPayload\":\"            Formatted payload with the message execution receipt\"}},\"messageStatus(bytes32)\":{\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"status\":\"          Message execution status\"}},\"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.\"},\"passAgentRoot()\":{\"details\":\"Will do nothing, if root optimistic period is not over.\",\"returns\":{\"rootPending\":\" Whether there is a pending agent merkle root left\"}},\"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.\"}},\"version\":1},\"userdoc\":{\"events\":{\"Executed(uint32,bytes32,bool)\":{\"notice\":\"Emitted when message is executed.\"},\"TipsRecorded(bytes32,uint256)\":{\"notice\":\"Emitted when message tips are recorded.\"}},\"kind\":\"user\",\"methods\":{\"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])\":{\"notice\":\"Accepts an attestation, which local `AgentManager` verified to have been signed by an active Notary for this chain. \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain. - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree. - Messages coming from chains included in the Attestation's snapshot could be proven. - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is in Dispute. \u003e - Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local `AgentManager`.\"},\"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.\"},\"attestationsAmount()\":{\"notice\":\"Returns the total amount of Notaries attestations that have been accepted.\"},\"destStatus()\":{\"notice\":\"Returns status of Destination contract as far as snapshot/agent roots are concerned\"},\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"notice\":\"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"getAttestation(uint256)\":{\"notice\":\"Returns a Notary-signed attestation with a given index. \u003e Index refers to the list of all attestations accepted by this contract.\"},\"getAttestationNonce(bytes32)\":{\"notice\":\"Returns attestation nonce for a given snapshot root.\"},\"getGasData(uint32)\":{\"notice\":\"Returns the gas data for a given chain from the latest accepted attestation with that chain.\"},\"inbox()\":{\"notice\":\"Returns the address of the local Inbox contract, which is treated as the \\\"source of truth\\\" for agent-signed statements.\"},\"initialize(bytes32)\":{\"notice\":\"Initializes Destination contract: - msg.sender is set as contract owner\"},\"isValidReceipt(bytes)\":{\"notice\":\"Checks the validity of the unsigned message receipt.\"},\"lastAttestationNonce(uint32)\":{\"notice\":\"Returns the nonce of the last attestation submitted by a Notary with a given agent index.\"},\"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\"},\"messageReceipt(bytes32)\":{\"notice\":\"Returns a formatted payload with the message receipt.\"},\"messageStatus(bytes32)\":{\"notice\":\"Returns message execution status: None/Failed/Success.\"},\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"},\"nextAgentRoot()\":{\"notice\":\"Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.\"},\"passAgentRoot()\":{\"notice\":\"Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\"},\"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\":\"Harness for standalone Go tests. Do not use for tests requiring interactions between messaging contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"DestinationHarness\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":"39fe2736","acceptOwnership()":"79ba5097","agentManager()":"7622f78d","agentStatus(address)":"28f3fac9","attestationsAmount()":"3cf7b120","destStatus()":"40989152","execute(bytes,bytes32[],bytes32[],uint8,uint64)":"883099bc","getAgent(uint256)":"2de5aaf7","getAttestation(uint256)":"29be4db2","getAttestationNonce(bytes32)":"4f127567","getGasData(uint32)":"d0dd0675","inbox()":"fb0e722b","initialize(bytes32)":"9498bd71","isValidReceipt(bytes)":"e2f006f7","lastAttestationNonce(uint32)":"305b29ee","latestDisputeStatus(uint32)":"dfadd81a","localDomain()":"8d3638f4","messageReceipt(bytes32)":"daa74a9e","messageStatus(bytes32)":"3c6cf473","multicall((bool,bytes)[])":"60fc8466","nextAgentRoot()":"55252dd1","openDispute(uint32,uint32)":"a2155c34","owner()":"8da5cb5b","passAgentRoot()":"a554d1e3","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","resolveDispute(uint32,uint32)":"61169218","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","version()":"54fd4d50"}},"solidity/DestinationHarness.t.sol:ExecutionHub":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"AlreadyExecuted","type":"error"},{"inputs":[],"name":"AlreadyFailed","type":"error"},{"inputs":[],"name":"CallerNotAgentManager","type":"error"},{"inputs":[],"name":"DisputeTimeoutNotOver","type":"error"},{"inputs":[],"name":"FlagOutOfRange","type":"error"},{"inputs":[],"name":"GasLimitTooLow","type":"error"},{"inputs":[],"name":"GasSuppliedTooLow","type":"error"},{"inputs":[],"name":"IncorrectDestinationDomain","type":"error"},{"inputs":[],"name":"IncorrectMagicValue","type":"error"},{"inputs":[],"name":"IncorrectOriginDomain","type":"error"},{"inputs":[],"name":"IncorrectSnapshotRoot","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"MessageOptimisticPeriod","type":"error"},{"inputs":[],"name":"NotaryInDispute","type":"error"},{"inputs":[],"name":"OccupiedMemory","type":"error"},{"inputs":[],"name":"PrecompileOutOfGas","type":"error"},{"inputs":[],"name":"TreeHeightTooLow","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedBaseMessage","type":"error"},{"inputs":[],"name":"UnformattedCallData","type":"error"},{"inputs":[],"name":"UnformattedCallDataPrefix","type":"error"},{"inputs":[],"name":"UnformattedMessage","type":"error"},{"inputs":[],"name":"UnformattedReceipt","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"remoteDomain","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"Executed","type":"event"},{"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":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"paddedTips","type":"uint256"}],"name":"TipsRecorded","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":"bytes","name":"msgPayload","type":"bytes"},{"internalType":"bytes32[]","name":"originProof","type":"bytes32[]"},{"internalType":"bytes32[]","name":"snapProof","type":"bytes32[]"},{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","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":"bytes32","name":"snapRoot","type":"bytes32"}],"name":"getAttestationNonce","outputs":[{"internalType":"uint32","name":"attNonce","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"name":"isValidReceipt","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":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageReceipt","outputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageStatus","outputs":[{"internalType":"enum MessageStatus","name":"status","type":"uint8"}],"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":{"events":{"Executed(uint32,bytes32,bool)":{"notice":"Emitted when message is executed."},"TipsRecorded(bytes32,uint256)":{"notice":"Emitted when message tips are recorded."}},"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."},"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"notice":"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"getAttestationNonce(bytes32)":{"notice":"Returns attestation nonce for a given snapshot root."},"inbox()":{"notice":"Returns the address of the local Inbox contract, which is treated as the \"source of truth\" for agent-signed statements."},"isValidReceipt(bytes)":{"notice":"Checks the validity of the unsigned message receipt."},"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"},"messageReceipt(bytes32)":{"notice":"Returns a formatted payload with the message receipt."},"messageStatus(bytes32)":{"notice":"Returns message execution status: None/Failed/Success."},"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":"`ExecutionHub` is a parent contract for `Destination`. It is responsible for the following: - Executing the messages that are proven against the saved Snapshot Merkle Roots. - Base messages are forwarded to the specified message recipient, ensuring that the original   execution request is fulfilled correctly. - Manager messages are forwarded to the local `AgentManager` contract. - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`). - Keeping track of message execution Receipts, as well as verify 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)."}},"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"details":"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.","params":{"gasLimit":"Gas limit for message execution","msgPayload":"Raw payload with a formatted message to execute","originProof":"Proof of inclusion of message in the Origin Merkle Tree","snapProof":"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree","stateIndex":"Index of Origin State in the Snapshot"}},"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)"}},"getAttestationNonce(bytes32)":{"details":"Will return 0 if the root is unknown."},"isValidReceipt(bytes)":{"details":"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.","params":{"rcptPayload":"Raw payload with Receipt data"},"returns":{"isValid":"         Whether the requested receipt 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)"}},"messageReceipt(bytes32)":{"details":"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.","params":{"messageHash":"Hash of the message payload"},"returns":{"rcptPayload":"            Formatted payload with the message execution receipt"}},"messageStatus(bytes32)":{"params":{"messageHash":"Hash of the message payload"},"returns":{"status":"          Message execution status"}},"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"},"_receiptData":{"details":"Messages coming from different origins will always have a different hash as origin domain is encoded into the formatted message. Thus we can use hash as a key instead of an (origin, hash) tuple."},"_rootData":{"details":"Tracks data for all saved snapshot roots"},"_roots":{"details":"All saved snapshot roots"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CallerNotAgentManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputeTimeoutNotOver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlagOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasSuppliedTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectDestinationDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectMagicValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectOriginDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSnapshotRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageOptimisticPeriod\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotaryInDispute\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OccupiedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrecompileOutOfGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TreeHeightTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedBaseMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedCallData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedCallDataPrefix\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedReceipt\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"remoteDomain\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"Executed\",\"type\":\"event\"},{\"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\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"}],\"name\":\"TipsRecorded\",\"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\":\"bytes\",\"name\":\"msgPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"originProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"snapProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":\"bytes32\",\"name\":\"snapRoot\",\"type\":\"bytes32\"}],\"name\":\"getAttestationNonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"name\":\"isValidReceipt\",\"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\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageReceipt\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageStatus\",\"outputs\":[{\"internalType\":\"enum MessageStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"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).\"}},\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"details\":\"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\",\"params\":{\"gasLimit\":\"Gas limit for message execution\",\"msgPayload\":\"Raw payload with a formatted message to execute\",\"originProof\":\"Proof of inclusion of message in the Origin Merkle Tree\",\"snapProof\":\"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\",\"stateIndex\":\"Index of Origin State in the Snapshot\"}},\"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)\"}},\"getAttestationNonce(bytes32)\":{\"details\":\"Will return 0 if the root is unknown.\"},\"isValidReceipt(bytes)\":{\"details\":\"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.\",\"params\":{\"rcptPayload\":\"Raw payload with Receipt data\"},\"returns\":{\"isValid\":\"         Whether the requested receipt 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)\"}},\"messageReceipt(bytes32)\":{\"details\":\"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\",\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"rcptPayload\":\"            Formatted payload with the message execution receipt\"}},\"messageStatus(bytes32)\":{\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"status\":\"          Message execution status\"}},\"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\"},\"_receiptData\":{\"details\":\"Messages coming from different origins will always have a different hash as origin domain is encoded into the formatted message. Thus we can use hash as a key instead of an (origin, hash) tuple.\"},\"_rootData\":{\"details\":\"Tracks data for all saved snapshot roots\"},\"_roots\":{\"details\":\"All saved snapshot roots\"}},\"version\":1},\"userdoc\":{\"events\":{\"Executed(uint32,bytes32,bool)\":{\"notice\":\"Emitted when message is executed.\"},\"TipsRecorded(bytes32,uint256)\":{\"notice\":\"Emitted when message tips are recorded.\"}},\"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.\"},\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"notice\":\"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"getAttestationNonce(bytes32)\":{\"notice\":\"Returns attestation nonce for a given snapshot root.\"},\"inbox()\":{\"notice\":\"Returns the address of the local Inbox contract, which is treated as the \\\"source of truth\\\" for agent-signed statements.\"},\"isValidReceipt(bytes)\":{\"notice\":\"Checks the validity of the unsigned message receipt.\"},\"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\"},\"messageReceipt(bytes32)\":{\"notice\":\"Returns a formatted payload with the message receipt.\"},\"messageStatus(bytes32)\":{\"notice\":\"Returns message execution status: None/Failed/Success.\"},\"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\":\"`ExecutionHub` is a parent contract for `Destination`. It is responsible for the following: - Executing the messages that are proven against the saved Snapshot Merkle Roots. - Base messages are forwarded to the specified message recipient, ensuring that the original   execution request is fulfilled correctly. - Manager messages are forwarded to the local `AgentManager` contract. - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`). - Keeping track of message execution Receipts, as well as verify their validity.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"ExecutionHub\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","agentManager()":"7622f78d","agentStatus(address)":"28f3fac9","execute(bytes,bytes32[],bytes32[],uint8,uint64)":"883099bc","getAgent(uint256)":"2de5aaf7","getAttestationNonce(bytes32)":"4f127567","inbox()":"fb0e722b","isValidReceipt(bytes)":"e2f006f7","latestDisputeStatus(uint32)":"dfadd81a","localDomain()":"8d3638f4","messageReceipt(bytes32)":"daa74a9e","messageStatus(bytes32)":"3c6cf473","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/DestinationHarness.t.sol:ExecutionHubEvents":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"uint32","name":"remoteDomain","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"paddedTips","type":"uint256"}],"name":"TipsRecorded","type":"event"}],"userDoc":{"events":{"Executed(uint32,bytes32,bool)":{"notice":"Emitted when message is executed."},"TipsRecorded(bytes32,uint256)":{"notice":"Emitted when message tips are recorded."}},"kind":"user","methods":{},"notice":"A collection of events emitted by the ExecutionHub contract","version":1},"developerDoc":{"events":{"Executed(uint32,bytes32,bool)":{"params":{"messageHash":"The keccak256 hash of the message that was executed","remoteDomain":"Remote domain where message originated","success":"Whether the message was executed successfully"}},"TipsRecorded(bytes32,uint256)":{"params":{"messageHash":"The keccak256 hash of the message that was executed","paddedTips":"Padded encoded paid tips information"}}},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"remoteDomain\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"Executed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"}],\"name\":\"TipsRecorded\",\"type\":\"event\"}],\"devdoc\":{\"events\":{\"Executed(uint32,bytes32,bool)\":{\"params\":{\"messageHash\":\"The keccak256 hash of the message that was executed\",\"remoteDomain\":\"Remote domain where message originated\",\"success\":\"Whether the message was executed successfully\"}},\"TipsRecorded(bytes32,uint256)\":{\"params\":{\"messageHash\":\"The keccak256 hash of the message that was executed\",\"paddedTips\":\"Padded encoded paid tips information\"}}},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"Executed(uint32,bytes32,bool)\":{\"notice\":\"Emitted when message is executed.\"},\"TipsRecorded(bytes32,uint256)\":{\"notice\":\"Emitted when message tips are recorded.\"}},\"kind\":\"user\",\"methods\":{},\"notice\":\"A collection of events emitted by the ExecutionHub contract\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"ExecutionHubEvents\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:GasDataLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220bdb3570a0523679468c22c0d9ed0bc5ebda43d60a1b0bf52ddfba7142ff0fc6564736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220bdb3570a0523679468c22c0d9ed0bc5ebda43d60a1b0bf52ddfba7142ff0fc6564736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"140111:7222:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;140111:7222:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"140111: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/DestinationHarness.t.sol\":\"GasDataLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:HeaderLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c69c3765316c2379d6d5099ab75b84418c45a8ad7c0a6a939fa02ddae80f3dc064736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c69c3765316c2379d6d5099ab75b84418c45a8ad7c0a6a939fa02ddae80f3dc064736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"148827:5145:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;148827:5145:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"148827: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/DestinationHarness.t.sol\":\"HeaderLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"IAgentManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"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/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"IAgentSecured\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"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/DestinationHarness.t.sol:IExecutionHub":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"msgPayload","type":"bytes"},{"internalType":"bytes32[]","name":"originProof","type":"bytes32[]"},{"internalType":"bytes32[]","name":"snapProof","type":"bytes32[]"},{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"uint64","name":"gasLimit","type":"uint64"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"snapRoot","type":"bytes32"}],"name":"getAttestationNonce","outputs":[{"internalType":"uint32","name":"attNonce","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"name":"isValidReceipt","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageReceipt","outputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"name":"messageStatus","outputs":[{"internalType":"enum MessageStatus","name":"status","type":"uint8"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"notice":"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient."},"getAttestationNonce(bytes32)":{"notice":"Returns attestation nonce for a given snapshot root."},"isValidReceipt(bytes)":{"notice":"Checks the validity of the unsigned message receipt."},"messageReceipt(bytes32)":{"notice":"Returns a formatted payload with the message receipt."},"messageStatus(bytes32)":{"notice":"Returns message execution status: None/Failed/Success."}},"version":1},"developerDoc":{"kind":"dev","methods":{"execute(bytes,bytes32[],bytes32[],uint8,uint64)":{"details":"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.","params":{"gasLimit":"Gas limit for message execution","msgPayload":"Raw payload with a formatted message to execute","originProof":"Proof of inclusion of message in the Origin Merkle Tree","snapProof":"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree","stateIndex":"Index of Origin State in the Snapshot"}},"getAttestationNonce(bytes32)":{"details":"Will return 0 if the root is unknown."},"isValidReceipt(bytes)":{"details":"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.","params":{"rcptPayload":"Raw payload with Receipt data"},"returns":{"isValid":"         Whether the requested receipt is valid."}},"messageReceipt(bytes32)":{"details":"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.","params":{"messageHash":"Hash of the message payload"},"returns":{"data":"            Formatted payload with the message execution receipt"}},"messageStatus(bytes32)":{"params":{"messageHash":"Hash of the message payload"},"returns":{"status":"          Message execution status"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"msgPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"originProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"snapProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"snapRoot\",\"type\":\"bytes32\"}],\"name\":\"getAttestationNonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"name\":\"isValidReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageReceipt\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"name\":\"messageStatus\",\"outputs\":[{\"internalType\":\"enum MessageStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"details\":\"Will revert if any of these is true:  - Message is not meant to be executed on this chain  - Message was sent from this chain  - Message payload is not properly formatted.  - Snapshot root (reconstructed from message hash and proofs) is unknown  - Snapshot root is known, but was submitted by an inactive Notary  - Snapshot root is known, but optimistic period for a message hasn't passed  - Provided gas limit is lower than the one requested in the message  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)  - Recipient reverted upon receiving a message Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\",\"params\":{\"gasLimit\":\"Gas limit for message execution\",\"msgPayload\":\"Raw payload with a formatted message to execute\",\"originProof\":\"Proof of inclusion of message in the Origin Merkle Tree\",\"snapProof\":\"Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\",\"stateIndex\":\"Index of Origin State in the Snapshot\"}},\"getAttestationNonce(bytes32)\":{\"details\":\"Will return 0 if the root is unknown.\"},\"isValidReceipt(bytes)\":{\"details\":\"Will revert if any of these is true:  - Receipt payload is not properly formatted.  - Receipt signer is not an active Notary.  - Receipt destination chain does not refer to this chain.\",\"params\":{\"rcptPayload\":\"Raw payload with Receipt data\"},\"returns\":{\"isValid\":\"         Whether the requested receipt is valid.\"}},\"messageReceipt(bytes32)\":{\"details\":\"Notaries could derive the tips, and the tips proof using the message payload, and submit the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\",\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"data\":\"            Formatted payload with the message execution receipt\"}},\"messageStatus(bytes32)\":{\"params\":{\"messageHash\":\"Hash of the message payload\"},\"returns\":{\"status\":\"          Message execution status\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"execute(bytes,bytes32[],bytes32[],uint8,uint64)\":{\"notice\":\"Attempts to prove inclusion of message into one of Snapshot Merkle Trees, previously submitted to this contract in a form of a signed Attestation. Proven message is immediately executed by passing its contents to the specified recipient.\"},\"getAttestationNonce(bytes32)\":{\"notice\":\"Returns attestation nonce for a given snapshot root.\"},\"isValidReceipt(bytes)\":{\"notice\":\"Checks the validity of the unsigned message receipt.\"},\"messageReceipt(bytes32)\":{\"notice\":\"Returns a formatted payload with the message receipt.\"},\"messageStatus(bytes32)\":{\"notice\":\"Returns message execution status: None/Failed/Success.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"IExecutionHub\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"execute(bytes,bytes32[],bytes32[],uint8,uint64)":"883099bc","getAttestationNonce(bytes32)":"4f127567","isValidReceipt(bytes)":"e2f006f7","messageReceipt(bytes32)":"daa74a9e","messageStatus(bytes32)":"3c6cf473"}},"solidity/DestinationHarness.t.sol:IMessageRecipient":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"origin","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"proofMaturity","type":"uint256"},{"internalType":"uint32","name":"version","type":"uint32"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"receiveBaseMessage","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"notice":"Message recipient needs to implement this function in order to receive cross-chain messages."}},"version":1},"developerDoc":{"kind":"dev","methods":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"details":"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \"message optimistic period\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.","params":{"content":"Raw bytes content of message","nonce":"Message nonce on the origin domain","origin":"Domain where message originated","proofMaturity":"Message's merkle proof age in seconds","sender":"Sender address on origin chain","version":"Message version specified by sender"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"origin\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"proofMaturity\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"receiveBaseMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"details\":\"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \\\"message optimistic period\\\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.\",\"params\":{\"content\":\"Raw bytes content of message\",\"nonce\":\"Message nonce on the origin domain\",\"origin\":\"Domain where message originated\",\"proofMaturity\":\"Message's merkle proof age in seconds\",\"sender\":\"Sender address on origin chain\",\"version\":\"Message version specified by sender\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"notice\":\"Message recipient needs to implement this function in order to receive cross-chain messages.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"IMessageRecipient\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":"032f287e"}},"solidity/DestinationHarness.t.sol:IStatementInbox":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"uint256","name":"index","type":"uint256"}],"name":"getGuardReport","outputs":[{"internalType":"bytes","name":"statementPayload","type":"bytes"},{"internalType":"bytes","name":"reportSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportsAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getStoredSignature","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"bytes","name":"srSignature","type":"bytes"},{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"submitStateReportWithAttestation","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"bytes","name":"srSignature","type":"bytes"},{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"submitStateReportWithSnapshot","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"bytes","name":"statePayload","type":"bytes"},{"internalType":"bytes","name":"srSignature","type":"bytes"},{"internalType":"bytes32[]","name":"snapProof","type":"bytes32[]"},{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"submitStateReportWithSnapshotProof","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"internalType":"bytes","name":"rcptSignature","type":"bytes"}],"name":"verifyReceipt","outputs":[{"internalType":"bool","name":"isValidReceipt","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"internalType":"bytes","name":"rrSignature","type":"bytes"}],"name":"verifyReceiptReport","outputs":[{"internalType":"bool","name":"isValidReport","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"},{"internalType":"bytes","name":"srSignature","type":"bytes"}],"name":"verifyStateReport","outputs":[{"internalType":"bool","name":"isValidReport","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"verifyStateWithAttestation","outputs":[{"internalType":"bool","name":"isValidState","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"verifyStateWithSnapshot","outputs":[{"internalType":"bool","name":"isValidState","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"stateIndex","type":"uint8"},{"internalType":"bytes","name":"statePayload","type":"bytes"},{"internalType":"bytes32[]","name":"snapProof","type":"bytes32[]"},{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"verifyStateWithSnapshotProof","outputs":[{"internalType":"bool","name":"isValidState","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getGuardReport(uint256)":{"notice":"Returns the Guard report with the given index stored in StatementInbox. \u003e Only reports that led to opening a Dispute are stored."},"getReportsAmount()":{"notice":"Returns the amount of Guard Reports stored in StatementInbox. \u003e Only reports that led to opening a Dispute are stored."},"getStoredSignature(uint256)":{"notice":"Returns the signature with the given index stored in StatementInbox."},"submitStateReportWithAttestation(uint8,bytes,bytes,bytes,bytes)":{"notice":"Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Attestation created from this Snapshot. \u003e StateReport is a Guard statement saying \"Reported state is invalid\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a StateReport and use other values from `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin. \u003e Will revert if any of these is true: \u003e - State Report signer is not an active Guard. \u003e - Snapshot payload is not properly formatted. \u003e - State index is out of range. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot. \u003e - The Guard or the Notary are already in a Dispute"},"submitStateReportWithSnapshot(uint8,bytes,bytes,bytes)":{"notice":"Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Snapshot. \u003e StateReport is a Guard statement saying \"Reported state is invalid\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a StateReport and use other values from `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin. \u003e Will revert if any of these is true: \u003e - State Report signer is not an active Guard. \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot signer is not an active Notary. \u003e - State index is out of range. \u003e - The Guard or the Notary are already in a Dispute"},"submitStateReportWithSnapshotProof(uint8,bytes,bytes,bytes32[],bytes,bytes)":{"notice":"Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation, as well as Notary signature for the Attestation. \u003e StateReport is a Guard statement saying \"Reported state is invalid\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a StateReport and use other values from `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin. \u003e Will revert if any of these is true: \u003e - State payload is not properly formatted. \u003e - State Report signer is not an active Guard. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof. \u003e - Snapshot Proof's first element does not match the State metadata. \u003e - Snapshot Proof length exceeds Snapshot Tree Height. \u003e - State index is out of range. \u003e - The Guard or the Notary are already in a Dispute"},"verifyReceipt(bytes,bytes)":{"notice":"Verifies a message receipt signed by the Notary. - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message). - Slashes the Notary, if the receipt is invalid. \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt signer is not an active Notary. \u003e - Receipt's destination chain does not refer to this chain."},"verifyReceiptReport(bytes,bytes)":{"notice":"Verifies a Guard's receipt report signature. - Does nothing, if the report is valid (if the reported receipt is invalid). - Slashes the Guard, if the report is invalid (if the reported receipt is valid). \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt Report signer is not an active Guard. \u003e - Receipt does not refer to this chain."},"verifyStateReport(bytes,bytes)":{"notice":"Verifies a Guard's state report signature.  - Does nothing, if the report is valid (if the reported state is invalid).  - Slashes the Guard, if the report is invalid (if the reported state is valid). \u003e Will revert if any of these is true: \u003e - State payload is not properly formatted. \u003e - State Report signer is not an active Guard. \u003e - Reported State does not refer to this chain."},"verifyStateWithAttestation(uint8,bytes,bytes,bytes)":{"notice":"Verifies a state from the snapshot, that was used for the Notary-signed attestation. - Does nothing, if the state is valid (matches the historical state of this contract). - Slashes the Notary, if the state is invalid. \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot. \u003e - Snapshot payload is not properly formatted. \u003e - State index is out of range. \u003e - State does not refer to this chain."},"verifyStateWithSnapshot(uint8,bytes,bytes)":{"notice":"Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary. - Does nothing, if the state is valid (matches the historical state of this contract). - Slashes the Agent, if the state is invalid. \u003e Will revert if any of these is true: \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot signer is not an active Agent. \u003e - State index is out of range. \u003e - State does not refer to this chain."},"verifyStateWithSnapshotProof(uint8,bytes,bytes32[],bytes,bytes)":{"notice":"Verifies a state from the snapshot, that was used for the Notary-signed attestation. - Does nothing, if the state is valid (matches the historical state of this contract). - Slashes the Notary, if the state is invalid. \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof. \u003e - Snapshot Proof's first element does not match the State metadata. \u003e - Snapshot Proof length exceeds Snapshot Tree Height. \u003e - State payload is not properly formatted. \u003e - State index is out of range. \u003e - State does not refer to this chain."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getGuardReport(uint256)":{"details":"Will revert if report with given index doesn't exist.","params":{"index":"Report index"},"returns":{"reportSignature":" Guard signature for the report","statementPayload":"Raw payload with statement that Guard reported as invalid"}},"getStoredSignature(uint256)":{"details":"Will revert if signature with given index doesn't exist.","params":{"index":"Signature index"},"returns":{"_0":"Raw payload with signature"}},"submitStateReportWithAttestation(uint8,bytes,bytes,bytes,bytes)":{"params":{"attPayload":"Raw payload with Attestation data","attSignature":"Notary signature for the Attestation","snapPayload":"Raw payload with Snapshot data","srSignature":"Guard signature for the report","stateIndex":"Index of the reported State in the Snapshot"},"returns":{"wasAccepted":"     Whether the Report was accepted (resulting in Dispute between the agents)"}},"submitStateReportWithSnapshot(uint8,bytes,bytes,bytes)":{"params":{"snapPayload":"Raw payload with Snapshot data","snapSignature":"Notary signature for the Snapshot","srSignature":"Guard signature for the report","stateIndex":"Index of the reported State in the Snapshot"},"returns":{"wasAccepted":"     Whether the Report was accepted (resulting in Dispute between the agents)"}},"submitStateReportWithSnapshotProof(uint8,bytes,bytes,bytes32[],bytes,bytes)":{"params":{"attPayload":"Raw payload with Attestation data","attSignature":"Notary signature for the Attestation","snapProof":"Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree","srSignature":"Guard signature for the report","stateIndex":"Index of the reported State in the Snapshot","statePayload":"Raw payload with State data that Guard reports as invalid"},"returns":{"wasAccepted":"     Whether the Report was accepted (resulting in Dispute between the agents)"}},"verifyReceipt(bytes,bytes)":{"params":{"rcptPayload":"Raw payload with Receipt data","rcptSignature":"Notary signature for the receipt"},"returns":{"isValidReceipt":"  Whether the provided receipt is valid.                          Notary is slashed, if return value is FALSE."}},"verifyReceiptReport(bytes,bytes)":{"params":{"rcptPayload":"Raw payload with Receipt data that Guard reports as invalid","rrSignature":"Guard signature for the report"},"returns":{"isValidReport":"   Whether the provided report is valid.                          Guard is slashed, if return value is FALSE."}},"verifyStateReport(bytes,bytes)":{"params":{"srSignature":"Guard signature for the report","statePayload":"Raw payload with State data that Guard reports as invalid"},"returns":{"isValidReport":"   Whether the provided report is valid.                          Guard is slashed, if return value is FALSE."}},"verifyStateWithAttestation(uint8,bytes,bytes,bytes)":{"params":{"attPayload":"Raw payload with Attestation data","attSignature":"Notary signature for the attestation","snapPayload":"Raw payload with snapshot data","stateIndex":"State index to check"},"returns":{"isValidState":"    Whether the provided state is valid.                          Notary is slashed, if return value is FALSE."}},"verifyStateWithSnapshot(uint8,bytes,bytes)":{"params":{"snapPayload":"Raw payload with snapshot data","snapSignature":"Agent signature for the snapshot","stateIndex":"State index to check"},"returns":{"isValidState":"    Whether the provided state is valid.                          Agent is slashed, if return value is FALSE."}},"verifyStateWithSnapshotProof(uint8,bytes,bytes32[],bytes,bytes)":{"params":{"attPayload":"Raw payload with Attestation data","attSignature":"Notary signature for the attestation","snapProof":"Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree","stateIndex":"Index of state in the snapshot","statePayload":"Raw payload with State data to check"},"returns":{"isValidState":"    Whether the provided state is valid.                          Notary is slashed, if return value is FALSE."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getGuardReport\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"statementPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReportsAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getStoredSignature\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"srSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"submitStateReportWithAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"srSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"submitStateReportWithSnapshot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"srSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"snapProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"submitStateReportWithSnapshotProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"}],\"name\":\"verifyReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidReceipt\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rrSignature\",\"type\":\"bytes\"}],\"name\":\"verifyReceiptReport\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidReport\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"srSignature\",\"type\":\"bytes\"}],\"name\":\"verifyStateReport\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidReport\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"verifyStateWithAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidState\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"verifyStateWithSnapshot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidState\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"snapProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"verifyStateWithSnapshotProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidState\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getGuardReport(uint256)\":{\"details\":\"Will revert if report with given index doesn't exist.\",\"params\":{\"index\":\"Report index\"},\"returns\":{\"reportSignature\":\" Guard signature for the report\",\"statementPayload\":\"Raw payload with statement that Guard reported as invalid\"}},\"getStoredSignature(uint256)\":{\"details\":\"Will revert if signature with given index doesn't exist.\",\"params\":{\"index\":\"Signature index\"},\"returns\":{\"_0\":\"Raw payload with signature\"}},\"submitStateReportWithAttestation(uint8,bytes,bytes,bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with Attestation data\",\"attSignature\":\"Notary signature for the Attestation\",\"snapPayload\":\"Raw payload with Snapshot data\",\"srSignature\":\"Guard signature for the report\",\"stateIndex\":\"Index of the reported State in the Snapshot\"},\"returns\":{\"wasAccepted\":\"     Whether the Report was accepted (resulting in Dispute between the agents)\"}},\"submitStateReportWithSnapshot(uint8,bytes,bytes,bytes)\":{\"params\":{\"snapPayload\":\"Raw payload with Snapshot data\",\"snapSignature\":\"Notary signature for the Snapshot\",\"srSignature\":\"Guard signature for the report\",\"stateIndex\":\"Index of the reported State in the Snapshot\"},\"returns\":{\"wasAccepted\":\"     Whether the Report was accepted (resulting in Dispute between the agents)\"}},\"submitStateReportWithSnapshotProof(uint8,bytes,bytes,bytes32[],bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with Attestation data\",\"attSignature\":\"Notary signature for the Attestation\",\"snapProof\":\"Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\",\"srSignature\":\"Guard signature for the report\",\"stateIndex\":\"Index of the reported State in the Snapshot\",\"statePayload\":\"Raw payload with State data that Guard reports as invalid\"},\"returns\":{\"wasAccepted\":\"     Whether the Report was accepted (resulting in Dispute between the agents)\"}},\"verifyReceipt(bytes,bytes)\":{\"params\":{\"rcptPayload\":\"Raw payload with Receipt data\",\"rcptSignature\":\"Notary signature for the receipt\"},\"returns\":{\"isValidReceipt\":\"  Whether the provided receipt is valid.                          Notary is slashed, if return value is FALSE.\"}},\"verifyReceiptReport(bytes,bytes)\":{\"params\":{\"rcptPayload\":\"Raw payload with Receipt data that Guard reports as invalid\",\"rrSignature\":\"Guard signature for the report\"},\"returns\":{\"isValidReport\":\"   Whether the provided report is valid.                          Guard is slashed, if return value is FALSE.\"}},\"verifyStateReport(bytes,bytes)\":{\"params\":{\"srSignature\":\"Guard signature for the report\",\"statePayload\":\"Raw payload with State data that Guard reports as invalid\"},\"returns\":{\"isValidReport\":\"   Whether the provided report is valid.                          Guard is slashed, if return value is FALSE.\"}},\"verifyStateWithAttestation(uint8,bytes,bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with Attestation data\",\"attSignature\":\"Notary signature for the attestation\",\"snapPayload\":\"Raw payload with snapshot data\",\"stateIndex\":\"State index to check\"},\"returns\":{\"isValidState\":\"    Whether the provided state is valid.                          Notary is slashed, if return value is FALSE.\"}},\"verifyStateWithSnapshot(uint8,bytes,bytes)\":{\"params\":{\"snapPayload\":\"Raw payload with snapshot data\",\"snapSignature\":\"Agent signature for the snapshot\",\"stateIndex\":\"State index to check\"},\"returns\":{\"isValidState\":\"    Whether the provided state is valid.                          Agent is slashed, if return value is FALSE.\"}},\"verifyStateWithSnapshotProof(uint8,bytes,bytes32[],bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with Attestation data\",\"attSignature\":\"Notary signature for the attestation\",\"snapProof\":\"Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\",\"stateIndex\":\"Index of state in the snapshot\",\"statePayload\":\"Raw payload with State data to check\"},\"returns\":{\"isValidState\":\"    Whether the provided state is valid.                          Notary is slashed, if return value is FALSE.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getGuardReport(uint256)\":{\"notice\":\"Returns the Guard report with the given index stored in StatementInbox. \u003e Only reports that led to opening a Dispute are stored.\"},\"getReportsAmount()\":{\"notice\":\"Returns the amount of Guard Reports stored in StatementInbox. \u003e Only reports that led to opening a Dispute are stored.\"},\"getStoredSignature(uint256)\":{\"notice\":\"Returns the signature with the given index stored in StatementInbox.\"},\"submitStateReportWithAttestation(uint8,bytes,bytes,bytes,bytes)\":{\"notice\":\"Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Attestation created from this Snapshot. \u003e StateReport is a Guard statement saying \\\"Reported state is invalid\\\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a StateReport and use other values from `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin. \u003e Will revert if any of these is true: \u003e - State Report signer is not an active Guard. \u003e - Snapshot payload is not properly formatted. \u003e - State index is out of range. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot. \u003e - The Guard or the Notary are already in a Dispute\"},\"submitStateReportWithSnapshot(uint8,bytes,bytes,bytes)\":{\"notice\":\"Accepts a Guard's state report signature, a Snapshot containing the reported State, as well as Notary signature for the Snapshot. \u003e StateReport is a Guard statement saying \\\"Reported state is invalid\\\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a StateReport and use other values from `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin. \u003e Will revert if any of these is true: \u003e - State Report signer is not an active Guard. \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot signer is not an active Notary. \u003e - State index is out of range. \u003e - The Guard or the Notary are already in a Dispute\"},\"submitStateReportWithSnapshotProof(uint8,bytes,bytes,bytes32[],bytes,bytes)\":{\"notice\":\"Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation, as well as Notary signature for the Attestation. \u003e StateReport is a Guard statement saying \\\"Reported state is invalid\\\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a StateReport and use other values from `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin. \u003e Will revert if any of these is true: \u003e - State payload is not properly formatted. \u003e - State Report signer is not an active Guard. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof. \u003e - Snapshot Proof's first element does not match the State metadata. \u003e - Snapshot Proof length exceeds Snapshot Tree Height. \u003e - State index is out of range. \u003e - The Guard or the Notary are already in a Dispute\"},\"verifyReceipt(bytes,bytes)\":{\"notice\":\"Verifies a message receipt signed by the Notary. - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message). - Slashes the Notary, if the receipt is invalid. \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt signer is not an active Notary. \u003e - Receipt's destination chain does not refer to this chain.\"},\"verifyReceiptReport(bytes,bytes)\":{\"notice\":\"Verifies a Guard's receipt report signature. - Does nothing, if the report is valid (if the reported receipt is invalid). - Slashes the Guard, if the report is invalid (if the reported receipt is valid). \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt Report signer is not an active Guard. \u003e - Receipt does not refer to this chain.\"},\"verifyStateReport(bytes,bytes)\":{\"notice\":\"Verifies a Guard's state report signature.  - Does nothing, if the report is valid (if the reported state is invalid).  - Slashes the Guard, if the report is invalid (if the reported state is valid). \u003e Will revert if any of these is true: \u003e - State payload is not properly formatted. \u003e - State Report signer is not an active Guard. \u003e - Reported State does not refer to this chain.\"},\"verifyStateWithAttestation(uint8,bytes,bytes,bytes)\":{\"notice\":\"Verifies a state from the snapshot, that was used for the Notary-signed attestation. - Does nothing, if the state is valid (matches the historical state of this contract). - Slashes the Notary, if the state is invalid. \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot. \u003e - Snapshot payload is not properly formatted. \u003e - State index is out of range. \u003e - State does not refer to this chain.\"},\"verifyStateWithSnapshot(uint8,bytes,bytes)\":{\"notice\":\"Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary. - Does nothing, if the state is valid (matches the historical state of this contract). - Slashes the Agent, if the state is invalid. \u003e Will revert if any of these is true: \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot signer is not an active Agent. \u003e - State index is out of range. \u003e - State does not refer to this chain.\"},\"verifyStateWithSnapshotProof(uint8,bytes,bytes32[],bytes,bytes)\":{\"notice\":\"Verifies a state from the snapshot, that was used for the Notary-signed attestation. - Does nothing, if the state is valid (matches the historical state of this contract). - Slashes the Notary, if the state is invalid. \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary. \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof. \u003e - Snapshot Proof's first element does not match the State metadata. \u003e - Snapshot Proof length exceeds Snapshot Tree Height. \u003e - State payload is not properly formatted. \u003e - State index is out of range. \u003e - State does not refer to this chain.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"IStatementInbox\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"getGuardReport(uint256)":"c495912b","getReportsAmount()":"756ed01d","getStoredSignature(uint256)":"ddeffa66","submitStateReportWithAttestation(uint8,bytes,bytes,bytes,bytes)":"243b9224","submitStateReportWithSnapshot(uint8,bytes,bytes,bytes)":"333138e2","submitStateReportWithSnapshotProof(uint8,bytes,bytes,bytes32[],bytes,bytes)":"be7e63da","verifyReceipt(bytes,bytes)":"c25aa585","verifyReceiptReport(bytes,bytes)":"91af2e5d","verifyStateReport(bytes,bytes)":"dfe39675","verifyStateWithAttestation(uint8,bytes,bytes,bytes)":"7d9978ae","verifyStateWithSnapshot(uint8,bytes,bytes)":"8671012e","verifyStateWithSnapshotProof(uint8,bytes,bytes32[],bytes,bytes)":"e3097af8"}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"Initializable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:InterfaceDestination":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"notaryIndex","type":"uint32"},{"internalType":"uint256","name":"sigIndex","type":"uint256"},{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes32","name":"agentRoot","type":"bytes32"},{"internalType":"ChainGas[]","name":"snapGas","type":"uint128[]"}],"name":"acceptAttestation","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"attestationsAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"destStatus","outputs":[{"internalType":"uint40","name":"snapRootTime","type":"uint40"},{"internalType":"uint40","name":"agentRootTime","type":"uint40"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAttestation","outputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"}],"name":"getGasData","outputs":[{"internalType":"GasData","name":"gasData","type":"uint96"},{"internalType":"uint256","name":"dataMaturity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"name":"lastAttestationNonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextAgentRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"passAgentRoot","outputs":[{"internalType":"bool","name":"rootPending","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":{"notice":"Accepts an attestation, which local `AgentManager` verified to have been signed by an active Notary for this chain. \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain. - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree. - Messages coming from chains included in the Attestation's snapshot could be proven. - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is in Dispute. \u003e - Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local `AgentManager`."},"attestationsAmount()":{"notice":"Returns the total amount of Notaries attestations that have been accepted."},"destStatus()":{"notice":"Returns status of Destination contract as far as snapshot/agent roots are concerned"},"getAttestation(uint256)":{"notice":"Returns a Notary-signed attestation with a given index. \u003e Index refers to the list of all attestations accepted by this contract."},"getGasData(uint32)":{"notice":"Returns the gas data for a given chain from the latest accepted attestation with that chain."},"lastAttestationNonce(uint32)":{"notice":"Returns the nonce of the last attestation submitted by a Notary with a given agent index."},"nextAgentRoot()":{"notice":"Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over."},"passAgentRoot()":{"notice":"Attempts to pass a quarantined Agent Merkle Root to a local Light Manager."}},"version":1},"developerDoc":{"kind":"dev","methods":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":{"params":{"agentRoot":"Agent Merkle Root from the Attestation","attPayload":"Raw payload with Attestation data","notaryIndex":"Index of Attestation Notary in Agent Merkle Tree","sigIndex":"Index of stored Notary signature","snapGas":"Gas data for each chain in the Attestation's snapshot"},"returns":{"wasAccepted":"     Whether the Attestation was accepted"}},"destStatus()":{"returns":{"agentRootTime":"   Timestamp when latest agent root was accepted","notaryIndex":"     Index of Notary who signed the latest agent root","snapRootTime":"    Timestamp when latest snapshot root was accepted"}},"getAttestation(uint256)":{"details":"Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.","params":{"index":"Attestation index"},"returns":{"attPayload":"      Raw payload with Attestation data","attSignature":"    Notary signature for the reported attestation"}},"getGasData(uint32)":{"details":"Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.","params":{"domain":"Domain for the chain"},"returns":{"dataMaturity":"    Gas data age in seconds","gasData":"         Gas data for the chain"}},"lastAttestationNonce(uint32)":{"details":"Will return zero if the Notary hasn't submitted any attestations yet."},"passAgentRoot()":{"details":"Will do nothing, if root optimistic period is not over.","returns":{"rootPending":" Whether there is a pending agent merkle root left"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"sigIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"},{\"internalType\":\"ChainGas[]\",\"name\":\"snapGas\",\"type\":\"uint128[]\"}],\"name\":\"acceptAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"attestationsAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destStatus\",\"outputs\":[{\"internalType\":\"uint40\",\"name\":\"snapRootTime\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"agentRootTime\",\"type\":\"uint40\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAttestation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"}],\"name\":\"getGasData\",\"outputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"dataMaturity\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"name\":\"lastAttestationNonce\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextAgentRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passAgentRoot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"rootPending\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])\":{\"params\":{\"agentRoot\":\"Agent Merkle Root from the Attestation\",\"attPayload\":\"Raw payload with Attestation data\",\"notaryIndex\":\"Index of Attestation Notary in Agent Merkle Tree\",\"sigIndex\":\"Index of stored Notary signature\",\"snapGas\":\"Gas data for each chain in the Attestation's snapshot\"},\"returns\":{\"wasAccepted\":\"     Whether the Attestation was accepted\"}},\"destStatus()\":{\"returns\":{\"agentRootTime\":\"   Timestamp when latest agent root was accepted\",\"notaryIndex\":\"     Index of Notary who signed the latest agent root\",\"snapRootTime\":\"    Timestamp when latest snapshot root was accepted\"}},\"getAttestation(uint256)\":{\"details\":\"Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit. Will return an empty signature if this contract is deployed on Synapse Chain.\",\"params\":{\"index\":\"Attestation index\"},\"returns\":{\"attPayload\":\"      Raw payload with Attestation data\",\"attSignature\":\"    Notary signature for the reported attestation\"}},\"getGasData(uint32)\":{\"details\":\"Will return empty values if there is no data for the domain, or if the notary who provided the data is in dispute.\",\"params\":{\"domain\":\"Domain for the chain\"},\"returns\":{\"dataMaturity\":\"    Gas data age in seconds\",\"gasData\":\"         Gas data for the chain\"}},\"lastAttestationNonce(uint32)\":{\"details\":\"Will return zero if the Notary hasn't submitted any attestations yet.\"},\"passAgentRoot()\":{\"details\":\"Will do nothing, if root optimistic period is not over.\",\"returns\":{\"rootPending\":\" Whether there is a pending agent merkle root left\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])\":{\"notice\":\"Accepts an attestation, which local `AgentManager` verified to have been signed by an active Notary for this chain. \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain. - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree. - Messages coming from chains included in the Attestation's snapshot could be proven. - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is in Dispute. \u003e - Attestation's snapshot root has been previously submitted. Note: agentRoot and snapGas have been verified by the local `AgentManager`.\"},\"attestationsAmount()\":{\"notice\":\"Returns the total amount of Notaries attestations that have been accepted.\"},\"destStatus()\":{\"notice\":\"Returns status of Destination contract as far as snapshot/agent roots are concerned\"},\"getAttestation(uint256)\":{\"notice\":\"Returns a Notary-signed attestation with a given index. \u003e Index refers to the list of all attestations accepted by this contract.\"},\"getGasData(uint32)\":{\"notice\":\"Returns the gas data for a given chain from the latest accepted attestation with that chain.\"},\"lastAttestationNonce(uint32)\":{\"notice\":\"Returns the nonce of the last attestation submitted by a Notary with a given agent index.\"},\"nextAgentRoot()\":{\"notice\":\"Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\"},\"passAgentRoot()\":{\"notice\":\"Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"InterfaceDestination\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"acceptAttestation(uint32,uint256,bytes,bytes32,uint128[])":"39fe2736","attestationsAmount()":"3cf7b120","destStatus()":"40989152","getAttestation(uint256)":"29be4db2","getGasData(uint32)":"d0dd0675","lastAttestationNonce(uint32)":"305b29ee","nextAgentRoot()":"55252dd1","passAgentRoot()":"a554d1e3"}},"solidity/DestinationHarness.t.sol:InterfaceInbox":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"attNotaryIndex","type":"uint32"},{"internalType":"uint32","name":"attNonce","type":"uint32"},{"internalType":"uint256","name":"paddedTips","type":"uint256"},{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"name":"passReceipt","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"internalType":"bytes","name":"rcptSignature","type":"bytes"},{"internalType":"uint256","name":"paddedTips","type":"uint256"},{"internalType":"bytes32","name":"headerHash","type":"bytes32"},{"internalType":"bytes32","name":"bodyHash","type":"bytes32"}],"name":"submitReceipt","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"internalType":"bytes","name":"rcptSignature","type":"bytes"},{"internalType":"bytes","name":"rrSignature","type":"bytes"}],"name":"submitReceiptReport","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"submitSnapshot","outputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes32","name":"agentRoot","type":"bytes32"},{"internalType":"uint256[]","name":"snapGas","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"verifyAttestation","outputs":[{"internalType":"bool","name":"isValidAttestation","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes","name":"arSignature","type":"bytes"}],"name":"verifyAttestationReport","outputs":[{"internalType":"bool","name":"isValidReport","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"passReceipt(uint32,uint32,uint256,bytes)":{"notice":"Passes the message execution receipt from Destination to the Summit contract to save. \u003e Will revert if any of these is true: \u003e - Called by anyone other than Destination."},"submitReceipt(bytes,bytes,uint256,bytes32,bytes32)":{"notice":"Accepts a receipt signed by a Notary and passes it to Summit contract to save. \u003e Receipt is a statement about message execution status on the remote chain. - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over. \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt signer is not an active Notary. \u003e - Receipt signer is in Dispute. \u003e - Receipt's snapshot root is unknown. \u003e - Provided tips could not be proven against the message hash."},"submitReceiptReport(bytes,bytes,bytes)":{"notice":"Accepts a Guard's receipt report signature, as well as Notary signature for the reported Receipt. \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain. \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt Report signer is not an active Guard. \u003e - Receipt signer is not an active Notary."},"submitSnapshot(bytes,bytes)":{"notice":"Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save. \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains. - Guard-signed snapshots: all the states in the snapshot become available for Notary signing. - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards. - Notary doesn't have to use states submitted by a single Guard in their snapshot. - Notary could then proceed to sign the attestation for their submitted snapshot. \u003e Will revert if any of these is true: \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot signer is not an active Agent. \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted. \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards. \u003e - Note: Agent will NOT be slashed for submitting such a snapshot."},"verifyAttestation(bytes,bytes)":{"notice":"Verifies an attestation signed by a Notary.  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).  - Slashes the Notary, if the attestation is invalid. \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary."},"verifyAttestationReport(bytes,bytes)":{"notice":"Verifies a Guard's attestation report signature.  - Does nothing, if the report is valid (if the reported attestation is invalid).  - Slashes the Guard, if the report is invalid (if the reported attestation is valid). \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation Report signer is not an active Guard."}},"version":1},"developerDoc":{"kind":"dev","methods":{"passReceipt(uint32,uint32,uint256,bytes)":{"details":"If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.","params":{"attNonce":"Nonce of the attestation used for proving the executed message","attNotaryIndex":"Index of the Notary who signed the attestation","paddedTips":"Tips for the message execution","rcptPayload":"Raw payload with message execution receipt"},"returns":{"wasAccepted":"     Whether the receipt was accepted"}},"submitReceipt(bytes,bytes,uint256,bytes32,bytes32)":{"params":{"bodyHash":"Hash of the message body excluding the tips","headerHash":"Hash of the message header","paddedTips":"Tips for the message execution","rcptPayload":"Raw payload with receipt data","rcptSignature":"Notary signature for the receipt"},"returns":{"wasAccepted":"     Whether the receipt was accepted"}},"submitReceiptReport(bytes,bytes,bytes)":{"params":{"rcptPayload":"Raw payload with Receipt data that Guard reports as invalid","rcptSignature":"Notary signature for the reported receipt","rrSignature":"Guard signature for the report"},"returns":{"wasAccepted":"     Whether the Report was accepted (resulting in Dispute between the agents)"}},"submitSnapshot(bytes,bytes)":{"details":"Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on the remote chain (the attestation contains only their merged hash). These are returned by this function, and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.","params":{"snapPayload":"Raw payload with snapshot data","snapSignature":"Agent signature for the snapshot"},"returns":{"agentRoot":"       Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)","attPayload":"      Raw payload with data for attestation derived from Notary snapshot.                          Empty payload, if a Guard snapshot was submitted.","snapGas":"         Gas data for each chain in the snapshot                          Empty list, if a Guard snapshot was submitted."}},"verifyAttestation(bytes,bytes)":{"params":{"attPayload":"Raw payload with Attestation data","attSignature":"Notary signature for the attestation"},"returns":{"isValidAttestation":"  Whether the provided attestation is valid.                              Notary is slashed, if return value is FALSE."}},"verifyAttestationReport(bytes,bytes)":{"params":{"arSignature":"Guard signature for the report","attPayload":"Raw payload with Attestation data that Guard reports as invalid"},"returns":{"isValidReport":"   Whether the provided report is valid.                          Guard is slashed, if return value is FALSE."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"attNotaryIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"name\":\"passReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"headerHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"bodyHash\",\"type\":\"bytes32\"}],\"name\":\"submitReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rrSignature\",\"type\":\"bytes\"}],\"name\":\"submitReceiptReport\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"submitSnapshot\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"snapGas\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"verifyAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidAttestation\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"arSignature\",\"type\":\"bytes\"}],\"name\":\"verifyAttestationReport\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValidReport\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"passReceipt(uint32,uint32,uint256,bytes)\":{\"details\":\"If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\",\"params\":{\"attNonce\":\"Nonce of the attestation used for proving the executed message\",\"attNotaryIndex\":\"Index of the Notary who signed the attestation\",\"paddedTips\":\"Tips for the message execution\",\"rcptPayload\":\"Raw payload with message execution receipt\"},\"returns\":{\"wasAccepted\":\"     Whether the receipt was accepted\"}},\"submitReceipt(bytes,bytes,uint256,bytes32,bytes32)\":{\"params\":{\"bodyHash\":\"Hash of the message body excluding the tips\",\"headerHash\":\"Hash of the message header\",\"paddedTips\":\"Tips for the message execution\",\"rcptPayload\":\"Raw payload with receipt data\",\"rcptSignature\":\"Notary signature for the receipt\"},\"returns\":{\"wasAccepted\":\"     Whether the receipt was accepted\"}},\"submitReceiptReport(bytes,bytes,bytes)\":{\"params\":{\"rcptPayload\":\"Raw payload with Receipt data that Guard reports as invalid\",\"rcptSignature\":\"Notary signature for the reported receipt\",\"rrSignature\":\"Guard signature for the report\"},\"returns\":{\"wasAccepted\":\"     Whether the Report was accepted (resulting in Dispute between the agents)\"}},\"submitSnapshot(bytes,bytes)\":{\"details\":\"Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on the remote chain (the attestation contains only their merged hash). These are returned by this function, and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\",\"params\":{\"snapPayload\":\"Raw payload with snapshot data\",\"snapSignature\":\"Agent signature for the snapshot\"},\"returns\":{\"agentRoot\":\"       Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\",\"attPayload\":\"      Raw payload with data for attestation derived from Notary snapshot.                          Empty payload, if a Guard snapshot was submitted.\",\"snapGas\":\"         Gas data for each chain in the snapshot                          Empty list, if a Guard snapshot was submitted.\"}},\"verifyAttestation(bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with Attestation data\",\"attSignature\":\"Notary signature for the attestation\"},\"returns\":{\"isValidAttestation\":\"  Whether the provided attestation is valid.                              Notary is slashed, if return value is FALSE.\"}},\"verifyAttestationReport(bytes,bytes)\":{\"params\":{\"arSignature\":\"Guard signature for the report\",\"attPayload\":\"Raw payload with Attestation data that Guard reports as invalid\"},\"returns\":{\"isValidReport\":\"   Whether the provided report is valid.                          Guard is slashed, if return value is FALSE.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"passReceipt(uint32,uint32,uint256,bytes)\":{\"notice\":\"Passes the message execution receipt from Destination to the Summit contract to save. \u003e Will revert if any of these is true: \u003e - Called by anyone other than Destination.\"},\"submitReceipt(bytes,bytes,uint256,bytes32,bytes32)\":{\"notice\":\"Accepts a receipt signed by a Notary and passes it to Summit contract to save. \u003e Receipt is a statement about message execution status on the remote chain. - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over. \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt signer is not an active Notary. \u003e - Receipt signer is in Dispute. \u003e - Receipt's snapshot root is unknown. \u003e - Provided tips could not be proven against the message hash.\"},\"submitReceiptReport(bytes,bytes,bytes)\":{\"notice\":\"Accepts a Guard's receipt report signature, as well as Notary signature for the reported Receipt. \u003e ReceiptReport is a Guard statement saying \\\"Reported receipt is invalid\\\". - This results in an opened Dispute between the Guard and the Notary. - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain. \u003e Will revert if any of these is true: \u003e - Receipt payload is not properly formatted. \u003e - Receipt Report signer is not an active Guard. \u003e - Receipt signer is not an active Notary.\"},\"submitSnapshot(bytes,bytes)\":{\"notice\":\"Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save. \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains. - Guard-signed snapshots: all the states in the snapshot become available for Notary signing. - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards. - Notary doesn't have to use states submitted by a single Guard in their snapshot. - Notary could then proceed to sign the attestation for their submitted snapshot. \u003e Will revert if any of these is true: \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot signer is not an active Agent. \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted. \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards. \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\"},\"verifyAttestation(bytes,bytes)\":{\"notice\":\"Verifies an attestation signed by a Notary.  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).  - Slashes the Notary, if the attestation is invalid. \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation signer is not an active Notary.\"},\"verifyAttestationReport(bytes,bytes)\":{\"notice\":\"Verifies a Guard's attestation report signature.  - Does nothing, if the report is valid (if the reported attestation is invalid).  - Slashes the Guard, if the report is invalid (if the reported attestation is valid). \u003e Will revert if any of these is true: \u003e - Attestation payload is not properly formatted. \u003e - Attestation Report signer is not an active Guard.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"InterfaceInbox\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"passReceipt(uint32,uint32,uint256,bytes)":"6b47b3bc","submitReceipt(bytes,bytes,uint256,bytes32,bytes32)":"b2a4b455","submitReceiptReport(bytes,bytes,bytes)":"89246503","submitSnapshot(bytes,bytes)":"4bb73ea5","verifyAttestation(bytes,bytes)":"0ca77473","verifyAttestationReport(bytes,bytes)":"31e8df5a"}},"solidity/DestinationHarness.t.sol:InterfaceLightManager":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"cancelProposedAgentRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"agentRoot_","type":"bytes32"}],"name":"proposeAgentRootWhenStuck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposedAgentRootData","outputs":[{"internalType":"bytes32","name":"agentRoot_","type":"bytes32"},{"internalType":"uint256","name":"proposedAt_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"msgOrigin","type":"uint32"},{"internalType":"uint256","name":"proofMaturity","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"remoteWithdrawTips","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolveProposedAgentRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"agentRoot_","type":"bytes32"}],"name":"setAgentRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"updateAgentStatus","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"cancelProposedAgentRoot()":{"notice":"Allows contract owner to cancel the previously proposed agent root."},"proposeAgentRootWhenStuck(bytes32)":{"notice":"Allows contract owner to set the agent root to resolve the \"stuck\" chain by proposing the new agent root. The contract owner will be able to resolve the proposed agent root after a certain period of time. Note: this function could be called multiple times, each time the timer will be reset. This could only be called if no fresh data has been submitted by the Notaries to the Inbox, indicating that the chain is stuck for one of the reasons: - All active Notaries are in Dispute. - No active Notaries exist under the current agent root."},"proposedAgentRootData()":{"notice":"Returns the latest proposed agent root and the timestamp when it was proposed."},"remoteWithdrawTips(uint32,uint256,address,uint256)":{"notice":"Withdraws locked base message tips from local Origin to the recipient."},"resolveProposedAgentRoot()":{"notice":"Allows contract owner to resolve the previously proposed agent root. This will update the agent root, allowing the agents to update their status, effectively resolving the \"stuck\" chain."},"setAgentRoot(bytes32)":{"notice":"Updates the root of Agent Merkle Tree that the Light Manager is tracking. Could be only called by a local Destination contract, which is supposed to verify the attested Agent Merkle Roots."},"updateAgentStatus(address,(uint8,uint32,uint32),bytes32[])":{"notice":"Updates agent status, using a proof against the latest known Agent Merkle Root."}},"version":1},"developerDoc":{"kind":"dev","methods":{"cancelProposedAgentRoot()":{"details":"Will revert if any of the following conditions is met: - Caller is not the contract owner. - No agent root was proposed."},"proposeAgentRootWhenStuck(bytes32)":{"details":"Will revert if any of the following conditions is met: - Caller is not the contract owner. - Agent root is empty. - The chain is not in a stuck state (has recently received a fresh data from the Notaries).","params":{"agentRoot_":"New Agent Merkle Root that is proposed to be set"}},"proposedAgentRootData()":{"details":"Will return zero values if no agent root was proposed, or if the proposed agent root was already resolved."},"remoteWithdrawTips(uint32,uint256,address,uint256)":{"details":"Could only be remote-called by BondingManager contract on Synapse Chain. Note: as an extra security check this function returns its own selector, so that Destination could verify that a \"remote\" function was called when executing a manager message.","params":{"amount":"Tips value to withdraw","recipient":"Address to withdraw tips to"}},"resolveProposedAgentRoot()":{"details":"Will revert if any of the following conditions is met: - Caller is not the contract owner. - No agent root was proposed. - Not enough time has passed since the agent root was proposed."},"setAgentRoot(bytes32)":{"params":{"agentRoot_":"New Agent Merkle Root"}},"updateAgentStatus(address,(uint8,uint32,uint32),bytes32[])":{"details":"Will revert if the provided proof doesn't match the latest merkle root.","params":{"agent":"Agent address","proof":"Merkle proof of Active status for the agent","status":"Structure specifying agent status: (flag, domain, index)"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"cancelProposedAgentRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"agentRoot_\",\"type\":\"bytes32\"}],\"name\":\"proposeAgentRootWhenStuck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposedAgentRootData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"agentRoot_\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"proposedAt_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"msgOrigin\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"proofMaturity\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"remoteWithdrawTips\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"magicValue\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolveProposedAgentRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"agentRoot_\",\"type\":\"bytes32\"}],\"name\":\"setAgentRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"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\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"updateAgentStatus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"cancelProposedAgentRoot()\":{\"details\":\"Will revert if any of the following conditions is met: - Caller is not the contract owner. - No agent root was proposed.\"},\"proposeAgentRootWhenStuck(bytes32)\":{\"details\":\"Will revert if any of the following conditions is met: - Caller is not the contract owner. - Agent root is empty. - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\",\"params\":{\"agentRoot_\":\"New Agent Merkle Root that is proposed to be set\"}},\"proposedAgentRootData()\":{\"details\":\"Will return zero values if no agent root was proposed, or if the proposed agent root was already resolved.\"},\"remoteWithdrawTips(uint32,uint256,address,uint256)\":{\"details\":\"Could only be remote-called by BondingManager contract on Synapse Chain. Note: as an extra security check this function returns its own selector, so that Destination could verify that a \\\"remote\\\" function was called when executing a manager message.\",\"params\":{\"amount\":\"Tips value to withdraw\",\"recipient\":\"Address to withdraw tips to\"}},\"resolveProposedAgentRoot()\":{\"details\":\"Will revert if any of the following conditions is met: - Caller is not the contract owner. - No agent root was proposed. - Not enough time has passed since the agent root was proposed.\"},\"setAgentRoot(bytes32)\":{\"params\":{\"agentRoot_\":\"New Agent Merkle Root\"}},\"updateAgentStatus(address,(uint8,uint32,uint32),bytes32[])\":{\"details\":\"Will revert if the provided proof doesn't match the latest merkle root.\",\"params\":{\"agent\":\"Agent address\",\"proof\":\"Merkle proof of Active status for the agent\",\"status\":\"Structure specifying agent status: (flag, domain, index)\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"cancelProposedAgentRoot()\":{\"notice\":\"Allows contract owner to cancel the previously proposed agent root.\"},\"proposeAgentRootWhenStuck(bytes32)\":{\"notice\":\"Allows contract owner to set the agent root to resolve the \\\"stuck\\\" chain by proposing the new agent root. The contract owner will be able to resolve the proposed agent root after a certain period of time. Note: this function could be called multiple times, each time the timer will be reset. This could only be called if no fresh data has been submitted by the Notaries to the Inbox, indicating that the chain is stuck for one of the reasons: - All active Notaries are in Dispute. - No active Notaries exist under the current agent root.\"},\"proposedAgentRootData()\":{\"notice\":\"Returns the latest proposed agent root and the timestamp when it was proposed.\"},\"remoteWithdrawTips(uint32,uint256,address,uint256)\":{\"notice\":\"Withdraws locked base message tips from local Origin to the recipient.\"},\"resolveProposedAgentRoot()\":{\"notice\":\"Allows contract owner to resolve the previously proposed agent root. This will update the agent root, allowing the agents to update their status, effectively resolving the \\\"stuck\\\" chain.\"},\"setAgentRoot(bytes32)\":{\"notice\":\"Updates the root of Agent Merkle Tree that the Light Manager is tracking. Could be only called by a local Destination contract, which is supposed to verify the attested Agent Merkle Roots.\"},\"updateAgentStatus(address,(uint8,uint32,uint32),bytes32[])\":{\"notice\":\"Updates agent status, using a proof against the latest known Agent Merkle Root.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"InterfaceLightManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"cancelProposedAgentRoot()":"91ea3c34","proposeAgentRootWhenStuck(bytes32)":"dbad9562","proposedAgentRootData()":"5396feef","remoteWithdrawTips(uint32,uint256,address,uint256)":"1fa07138","resolveProposedAgentRoot()":"38416281","setAgentRoot(bytes32)":"58668176","updateAgentStatus(address,(uint8,uint32,uint32),bytes32[])":"cbd05965"}},"solidity/DestinationHarness.t.sol:MemViewLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220dd55ee53b6a0b1c7656dce4207af26b291f900c13be4e8776190ba60881ec43964736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220dd55ee53b6a0b1c7656dce4207af26b291f900c13be4e8776190ba60881ec43964736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"108631:19162:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;108631:19162:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"108631: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/DestinationHarness.t.sol\":\"MemViewLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:MerkleMath":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205488e8d097c2d8c37c7555b16623fa9379378871cbb80167ae753df3c9217ec664736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205488e8d097c2d8c37c7555b16623fa9379378871cbb80167ae753df3c9217ec664736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"127836:9845:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;127836:9845:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"127836: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/DestinationHarness.t.sol\":\"MerkleMath\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:MessageLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212200aec72f8987ff2ef00cbffba1eb43d9caeee88295ae8214d46a8672c3e1d9bda64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212200aec72f8987ff2ef00cbffba1eb43d9caeee88295ae8214d46a8672c3e1d9bda64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"256190:5074:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;256190:5074:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"256190: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/DestinationHarness.t.sol\":\"MessageLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"MessagingBase\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"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/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"MultiCallable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"multicall((bool,bytes)[])":"60fc8466"}},"solidity/DestinationHarness.t.sol:NumberLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220bec47c0883a87a4681c1637a539051ca808f3ecd419126feab8abd3f7317a38a64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220bec47c0883a87a4681c1637a539051ca808f3ecd419126feab8abd3f7317a38a64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"35681:4887:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;35681:4887:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"35681: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/DestinationHarness.t.sol\":\"NumberLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"Ownable2StepUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"OwnableUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"owner()":"8da5cb5b","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}},"solidity/DestinationHarness.t.sol:ReceiptLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c7c1f0539c867ef5127b69c1a3a5a5b3bed1bacc8f0f308cf960f34ee7a1e43664736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c7c1f0539c867ef5127b69c1a3a5a5b3bed1bacc8f0f308cf960f34ee7a1e43664736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"206119:6371:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;206119:6371:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"206119:6371:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`. - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not   included in the receipt. - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an   executed message. - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both   receipts will be considered valid. # Memory layout of Receipt fields | Position   | Field         | Type    | Bytes | Description                                      | | ---------- | ------------- | ------- | ----- | ------------------------------------------------ | | [000..004) | origin        | uint32  | 4     | Domain where message originated                  | | [004..008) | destination   | uint32  | 4     | Domain where message was executed                | | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              | | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       | | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       | | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root | | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     | | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"OFFSET_ORIGIN":{"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_ORIGIN\":{\"details\":\"The variables below are not supposed to be used outside of the library directly.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`. - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not   included in the receipt. - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an   executed message. - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both   receipts will be considered valid. # Memory layout of Receipt fields | Position   | Field         | Type    | Bytes | Description                                      | | ---------- | ------------- | ------- | ----- | ------------------------------------------------ | | [000..004) | origin        | uint32  | 4     | Domain where message originated                  | | [004..008) | destination   | uint32  | 4     | Domain where message was executed                | | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              | | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       | | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       | | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root | | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     | | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"ReceiptLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:ReentrancyGuardUpgradeable":{"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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].","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\":\"Contract module that helps prevent reentrant calls to a function. Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier available, which can be applied to functions to make sure there are no nested (reentrant) calls to them. Note that because there is a single `nonReentrant` guard, functions marked as `nonReentrant` may not call one another. This can be worked around by making those functions `private`, and then adding `external` `nonReentrant` entry points to them. TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\",\"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/DestinationHarness.t.sol\":\"ReentrancyGuardUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:RequestLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122082bc7e8993995fa85841a6fbb80a916761b7852652ac0aa0aa811743d098793764736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122082bc7e8993995fa85841a6fbb80a916761b7852652ac0aa0aa811743d098793764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"41682:2478:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;41682:2478:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"41682: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/DestinationHarness.t.sol\":\"RequestLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:SafeCall":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122026993598efe391f3d1b5035ebfe33a02cab0209ea9dbc89ebf146b3e4d45ec3f64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122026993598efe391f3d1b5035ebfe33a02cab0209ea9dbc89ebf146b3e4d45ec3f64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"33046:1380:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;33046:1380:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"33046:1380:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for performing safe calls to the recipients. Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall","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 performing safe calls to the recipients. Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"SafeCall\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:SafeCast":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220879fa29bc280b47a3a36c631d115818d12380130c962c01514c5a169f32381e264736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220879fa29bc280b47a3a36c631d115818d12380130c962c01514c5a169f32381e264736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"54464:34153:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;54464:34153:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"54464: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/DestinationHarness.t.sol\":\"SafeCast\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:SnapshotLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122085d25746d588d140d2866dc53710c4e81db5ffcedbd15ccfb26483b3748f54ba64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122085d25746d588d140d2866dc53710c4e81db5ffcedbd15ccfb26483b3748f54ba64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"245160:7877:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;245160:7877:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"245160:7877:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"# Snapshot Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains. In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs. ## Snapshot usage - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity. - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.   - They are expected to form snapshots with Origin states for this set of chains,   sign and submit them to Summit contract. - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.   - They should be forming their own snapshots using states from snapshots of any of the Guards.   - The states for the Notary snapshots don't have to come from the same Guard snapshot,   or don't even have to be submitted by the same Guard. - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as   a proof of liveliness for Guards monitoring these Origins. ## Snapshot validity - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there. - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract. # Snapshot memory layout | Position   | Field       | Type  | Bytes | Description                  | | ---------- | ----------- | ----- | ----- | ---------------------------- | | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   | | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   | | ...        | ...         | ...   | 50    | ...                          | | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |","version":1},"developerDoc":{"details":"Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"# Snapshot Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains. In short, snapshot is a list of \\\"State\\\" structs. See State.sol for details about the \\\"State\\\" structs. ## Snapshot usage - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity. - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.   - They are expected to form snapshots with Origin states for this set of chains,   sign and submit them to Summit contract. - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.   - They should be forming their own snapshots using states from snapshots of any of the Guards.   - The states for the Notary snapshots don't have to come from the same Guard snapshot,   or don't even have to be submitted by the same Guard. - With their signature, Notary effectively \\\"notarizes\\\" the work that some Guards have done in Summit contract.   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as   a proof of liveliness for Guards monitoring these Origins. ## Snapshot validity - Snapshot is considered \\\"valid\\\" in Origin, if every state referring to that Origin is valid there. - Snapshot is considered \\\"globally valid\\\", if it is \\\"valid\\\" in every Origin contract. # Snapshot memory layout | Position   | Field       | Type  | Bytes | Description                  | | ---------- | ----------- | ----- | ----- | ---------------------------- | | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   | | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   | | ...        | ...         | ...   | 50    | ...                          | | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/DestinationHarness.t.sol\":\"SnapshotLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:StateLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220511039e934cbbd74b36fc892602fbfa971649f06a9162e5cf7b7e8de456cb90c64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220511039e934cbbd74b36fc892602fbfa971649f06a9162e5cf7b7e8de456cb90c64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"229139:7325:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;229139:7325:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"229139: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/DestinationHarness.t.sol\":\"StateLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:StructureUtils":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220ab26f5aab55b088d8ef220cb44aa97b888cdd32b5800194dd433dce1847c7ec464736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220ab26f5aab55b088d8ef220cb44aa97b888cdd32b5800194dd433dce1847c7ec464736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"106332:1198:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;106332:1198:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"106332: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/DestinationHarness.t.sol\":\"StructureUtils\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:TipsLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220afea53621d6717ff10a392d096cd5ff75481a893bde5c2b45eac2636b3367ddd64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220afea53621d6717ff10a392d096cd5ff75481a893bde5c2b45eac2636b3367ddd64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"215031:6743:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;215031:6743:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"215031: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/DestinationHarness.t.sol\":\"TipsLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.sol:TypeCasts":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220eb6faabfcd2973da6e8534ba57f40846dd07a4d18b22b0f247d7e45e1d8ea7c564736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220eb6faabfcd2973da6e8534ba57f40846dd07a4d18b22b0f247d7e45e1d8ea7c564736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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":"34461:350:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;34461:350:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"34461: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/DestinationHarness.t.sol\":\"TypeCasts\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{}},"solidity/DestinationHarness.t.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/DestinationEvents.sol\n\n/// @notice A collection of events emitted by the Destination contract\nabstract contract DestinationEvents {\n    event AgentRootAccepted(bytes32 agentRoot);\n}\n\n// contracts/events/ExecutionHubEvents.sol\n\n/// @notice A collection of events emitted by the ExecutionHub contract\nabstract contract ExecutionHubEvents {\n    /**\n     * @notice Emitted when message is executed.\n     * @param remoteDomain  Remote domain where message originated\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param success       Whether the message was executed successfully\n     */\n    event Executed(uint32 indexed remoteDomain, bytes32 indexed messageHash, bool success);\n\n    /**\n     * @notice Emitted when message tips are recorded.\n     * @param messageHash   The keccak256 hash of the message that was executed\n     * @param paddedTips    Padded encoded paid tips information\n     */\n    event TipsRecorded(bytes32 messageHash, uint256 paddedTips);\n}\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/IStatementInbox.sol\n\ninterface IStatementInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshot()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Notary.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param snapSignature     Notary signature for the Snapshot\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshot(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory snapSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a Snapshot containing the reported State,\n     * as well as Notary signature for the Attestation created from this Snapshot.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithAttestation()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param srSignature       Guard signature for the report\n     * @param snapPayload       Raw payload with Snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithAttestation(\n        uint8 stateIndex,\n        bytes memory srSignature,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's state report signature, a proof of inclusion of the reported State in an Attestation,\n     * as well as Notary signature for the Attestation.\n     * \u003e StateReport is a Guard statement saying \"Reported state is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a StateReport and use other values from\n     * `verifyStateWithSnapshotProof()` successful call that led to Notary being slashed in remote Origin.\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State index is out of range.\n     * \u003e - The Guard or the Notary are already in a Dispute\n     * @param stateIndex        Index of the reported State in the Snapshot\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @param snapProof         Proof of inclusion of reported State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the Attestation\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitStateReportWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes memory srSignature,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies a message receipt signed by the Notary.\n     * - Does nothing, if the receipt is valid (matches the saved receipt data for the referenced message).\n     * - Slashes the Notary, if the receipt is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt's destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @return isValidReceipt   Whether the provided receipt is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n        external\n        returns (bool isValidReceipt);\n\n    /**\n     * @notice Verifies a Guard's receipt report signature.\n     * - Does nothing, if the report is valid (if the reported receipt is invalid).\n     * - Slashes the Guard, if the report is invalid (if the reported receipt is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rrSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n        external\n        returns (bool isValidReport);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from the Snapshot.\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithAttestation(\n        uint8 stateIndex,\n        bytes memory snapPayload,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot, that was used for the Notary-signed attestation.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Notary, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * \u003e - Attestation's snapshot root is not equal to Merkle Root derived from State and Snapshot Proof.\n     * \u003e - Snapshot Proof's first element does not match the State metadata.\n     * \u003e - Snapshot Proof length exceeds Snapshot Tree Height.\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        Index of state in the snapshot\n     * @param statePayload      Raw payload with State data to check\n     * @param snapProof         Proof of inclusion of provided State's Left Leaf into Snapshot Merkle Tree\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidState     Whether the provided state is valid.\n     *                          Notary is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshotProof(\n        uint8 stateIndex,\n        bytes memory statePayload,\n        bytes32[] memory snapProof,\n        bytes memory attPayload,\n        bytes memory attSignature\n    ) external returns (bool isValidState);\n\n    /**\n     * @notice Verifies a state from the snapshot (a list of states) signed by a Guard or a Notary.\n     * - Does nothing, if the state is valid (matches the historical state of this contract).\n     * - Slashes the Agent, if the state is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - State index is out of range.\n     * \u003e - State does not refer to this chain.\n     * @param stateIndex        State index to check\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return isValidState     Whether the provided state is valid.\n     *                          Agent is slashed, if return value is FALSE.\n     */\n    function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bool isValidState);\n\n    /**\n     * @notice Verifies a Guard's state report signature.\n     *  - Does nothing, if the report is valid (if the reported state is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported state is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - State payload is not properly formatted.\n     * \u003e - State Report signer is not an active Guard.\n     * \u003e - Reported State does not refer to this chain.\n     * @param statePayload      Raw payload with State data that Guard reports as invalid\n     * @param srSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n        external\n        returns (bool isValidReport);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the amount of Guard Reports stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     */\n    function getReportsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns the Guard report with the given index stored in StatementInbox.\n     * \u003e Only reports that led to opening a Dispute are stored.\n     * @dev Will revert if report with given index doesn't exist.\n     * @param index             Report index\n     * @return statementPayload Raw payload with statement that Guard reported as invalid\n     * @return reportSignature  Guard signature for the report\n     */\n    function getGuardReport(uint256 index)\n        external\n        view\n        returns (bytes memory statementPayload, bytes memory reportSignature);\n\n    /**\n     * @notice Returns the signature with the given index stored in StatementInbox.\n     * @dev Will revert if signature with given index doesn't exist.\n     * @param index     Signature index\n     * @return          Raw payload with signature\n     */\n    function getStoredSignature(uint256 index) external view returns (bytes memory);\n}\n\n// contracts/interfaces/InterfaceInbox.sol\n\ninterface InterfaceInbox {\n    // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Accepts a snapshot signed by a Guard or a Notary and passes it to Summit contract to save.\n     * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n     * - Guard-signed snapshots: all the states in the snapshot become available for Notary signing.\n     * - Notary-signed snapshots: Snapshot Merkle Root is saved for valid snapshots, i.e.\n     * snapshots which are only using states previously submitted by any of the Guards.\n     * - Notary doesn't have to use states submitted by a single Guard in their snapshot.\n     * - Notary could then proceed to sign the attestation for their submitted snapshot.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Snapshot payload is not properly formatted.\n     * \u003e - Snapshot signer is not an active Agent.\n     * \u003e - Agent snapshot contains a state with a nonce smaller or equal then they have previously submitted.\n     * \u003e - Notary snapshot contains a state that hasn't been previously submitted by any of the Guards.\n     * \u003e - Note: Agent will NOT be slashed for submitting such a snapshot.\n     * @dev Notary will need to provide both `agentRoot` and `snapGas` when submitting an attestation on\n     * the remote chain (the attestation contains only their merged hash). These are returned by this function,\n     * and could be also obtained by calling `getAttestation(nonce)` or `getLatestNotaryAttestation(notary)`.\n     * @param snapPayload       Raw payload with snapshot data\n     * @param snapSignature     Agent signature for the snapshot\n     * @return attPayload       Raw payload with data for attestation derived from Notary snapshot.\n     *                          Empty payload, if a Guard snapshot was submitted.\n     * @return agentRoot        Current root of the Agent Merkle Tree (zero, if a Guard snapshot was submitted)\n     * @return snapGas          Gas data for each chain in the snapshot\n     *                          Empty list, if a Guard snapshot was submitted.\n     */\n    function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n        external\n        returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n    /**\n     * @notice Accepts a receipt signed by a Notary and passes it to Summit contract to save.\n     * \u003e Receipt is a statement about message execution status on the remote chain.\n     * - This will distribute the message tips across the off-chain actors once the receipt optimistic period is over.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt signer is not an active Notary.\n     * \u003e - Receipt signer is in Dispute.\n     * \u003e - Receipt's snapshot root is unknown.\n     * \u003e - Provided tips could not be proven against the message hash.\n     * @param rcptPayload       Raw payload with receipt data\n     * @param rcptSignature     Notary signature for the receipt\n     * @param paddedTips        Tips for the message execution\n     * @param headerHash        Hash of the message header\n     * @param bodyHash          Hash of the message body excluding the tips\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function submitReceipt(\n        bytes memory rcptPayload,\n        bytes memory rcptSignature,\n        uint256 paddedTips,\n        bytes32 headerHash,\n        bytes32 bodyHash\n    ) external returns (bool wasAccepted);\n\n    /**\n     * @notice Accepts a Guard's receipt report signature, as well as Notary signature\n     * for the reported Receipt.\n     * \u003e ReceiptReport is a Guard statement saying \"Reported receipt is invalid\".\n     * - This results in an opened Dispute between the Guard and the Notary.\n     * - Note: Guard could (but doesn't have to) form a ReceiptReport and use receipt signature from\n     * `verifyReceipt()` successful call that led to Notary being slashed in Summit on Synapse Chain.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Receipt payload is not properly formatted.\n     * \u003e - Receipt Report signer is not an active Guard.\n     * \u003e - Receipt signer is not an active Notary.\n     * @param rcptPayload       Raw payload with Receipt data that Guard reports as invalid\n     * @param rcptSignature     Notary signature for the reported receipt\n     * @param rrSignature       Guard signature for the report\n     * @return wasAccepted      Whether the Report was accepted (resulting in Dispute between the agents)\n     */\n    function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n        external\n        returns (bool wasAccepted);\n\n    /**\n     * @notice Passes the message execution receipt from Destination to the Summit contract to save.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than Destination.\n     * @dev If a receipt is not accepted, any of the Notaries can submit it later using `submitReceipt`.\n     * @param attNotaryIndex    Index of the Notary who signed the attestation\n     * @param attNonce          Nonce of the attestation used for proving the executed message\n     * @param paddedTips        Tips for the message execution\n     * @param rcptPayload       Raw payload with message execution receipt\n     * @return wasAccepted      Whether the receipt was accepted\n     */\n    function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n        external\n        returns (bool wasAccepted);\n\n    // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n    /**\n     * @notice Verifies an attestation signed by a Notary.\n     *  - Does nothing, if the attestation is valid (was submitted by this Notary as a snapshot).\n     *  - Slashes the Notary, if the attestation is invalid.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is not an active Notary.\n     * @param attPayload        Raw payload with Attestation data\n     * @param attSignature      Notary signature for the attestation\n     * @return isValidAttestation   Whether the provided attestation is valid.\n     *                              Notary is slashed, if return value is FALSE.\n     */\n    function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n        external\n        returns (bool isValidAttestation);\n\n    /**\n     * @notice Verifies a Guard's attestation report signature.\n     *  - Does nothing, if the report is valid (if the reported attestation is invalid).\n     *  - Slashes the Guard, if the report is invalid (if the reported attestation is valid).\n     * \u003e Will revert if any of these is true:\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation Report signer is not an active Guard.\n     * @param attPayload        Raw payload with Attestation data that Guard reports as invalid\n     * @param arSignature       Guard signature for the report\n     * @return isValidReport    Whether the provided report is valid.\n     *                          Guard is slashed, if return value is FALSE.\n     */\n    function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n        external\n        returns (bool isValidReport);\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/SafeCall.sol\n\n/// @notice Library for performing safe calls to the recipients.\n/// Inspired by https://github.com/nomad-xyz/ExcessivelySafeCall\nlibrary SafeCall {\n    /// @notice Performs a call to the recipient using the provided gas limit, msg.value and payload\n    /// in a safe way:\n    /// - If the recipient is not a contract, false is returned instead of reverting.\n    /// - If the recipient call reverts for any reason, false is returned instead of reverting.\n    /// - If the recipient call succeeds, true is returned, and any returned data is ignored.\n    /// @param recipient        The recipient of the call\n    /// @param gasLimit         The gas limit to use for the call\n    /// @param msgValue         The msg.value to use for the call\n    /// @param payload          The payload to use for the call\n    /// @return success         True if the call succeeded, false otherwise\n    function safeCall(address recipient, uint256 gasLimit, uint256 msgValue, bytes memory payload)\n        internal\n        returns (bool success)\n    {\n        // Exit early if the recipient is not a contract\n        if (recipient.code.length == 0) return false;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Perform the call to the recipient, while ignoring any returned data\n            // call(g, a, v, in, insize, out, outsize) =\u003e returns 0 on error, 1 on success\n            success := call(gasLimit, recipient, msgValue, add(payload, 0x20), mload(payload), 0, 0)\n        }\n    }\n}\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/Address.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 Address {\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// 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/interfaces/IExecutionHub.sol\n\ninterface IExecutionHub {\n    /**\n     * @notice Attempts to prove inclusion of message into one of Snapshot Merkle Trees,\n     * previously submitted to this contract in a form of a signed Attestation.\n     * Proven message is immediately executed by passing its contents to the specified recipient.\n     * @dev Will revert if any of these is true:\n     *  - Message is not meant to be executed on this chain\n     *  - Message was sent from this chain\n     *  - Message payload is not properly formatted.\n     *  - Snapshot root (reconstructed from message hash and proofs) is unknown\n     *  - Snapshot root is known, but was submitted by an inactive Notary\n     *  - Snapshot root is known, but optimistic period for a message hasn't passed\n     *  - Provided gas limit is lower than the one requested in the message\n     *  - Recipient doesn't implement a `handle` method (refer to IMessageRecipient.sol)\n     *  - Recipient reverted upon receiving a message\n     * Note: refer to libs/memory/State.sol for details about Origin State's sub-leafs.\n     * @param msgPayload    Raw payload with a formatted message to execute\n     * @param originProof   Proof of inclusion of message in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State's Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @param gasLimit      Gas limit for message execution\n     */\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns attestation nonce for a given snapshot root.\n     * @dev Will return 0 if the root is unknown.\n     */\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce);\n\n    /**\n     * @notice Checks the validity of the unsigned message receipt.\n     * @dev Will revert if any of these is true:\n     *  - Receipt payload is not properly formatted.\n     *  - Receipt signer is not an active Notary.\n     *  - Receipt destination chain does not refer to this chain.\n     * @param rcptPayload       Raw payload with Receipt data\n     * @return isValid          Whether the requested receipt is valid.\n     */\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns message execution status: None/Failed/Success.\n     * @param messageHash       Hash of the message payload\n     * @return status           Message execution status\n     */\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status);\n\n    /**\n     * @notice Returns a formatted payload with the message receipt.\n     * @dev Notaries could derive the tips, and the tips proof using the message payload, and submit\n     * the signed receipt with the proof of tips to `Summit` in order to initiate tips distribution.\n     * @param messageHash       Hash of the message payload\n     * @return data             Formatted payload with the message execution receipt\n     */\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory data);\n}\n\n// contracts/interfaces/InterfaceDestination.sol\n\ninterface InterfaceDestination {\n    /**\n     * @notice Attempts to pass a quarantined Agent Merkle Root to a local Light Manager.\n     * @dev Will do nothing, if root optimistic period is not over.\n     * @return rootPending  Whether there is a pending agent merkle root left\n     */\n    function passAgentRoot() external returns (bool rootPending);\n\n    /**\n     * @notice Accepts an attestation, which local `AgentManager` verified to have been signed\n     * by an active Notary for this chain.\n     * \u003e Attestation is created whenever a Notary-signed snapshot is saved in Summit on Synapse Chain.\n     * - Saved Attestation could be later used to prove the inclusion of message in the Origin Merkle Tree.\n     * - Messages coming from chains included in the Attestation's snapshot could be proven.\n     * - Proof only exists for messages that were sent prior to when the Attestation's snapshot was taken.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Called by anyone other than local `AgentManager`.\n     * \u003e - Attestation payload is not properly formatted.\n     * \u003e - Attestation signer is in Dispute.\n     * \u003e - Attestation's snapshot root has been previously submitted.\n     * Note: agentRoot and snapGas have been verified by the local `AgentManager`.\n     * @param notaryIndex       Index of Attestation Notary in Agent Merkle Tree\n     * @param sigIndex          Index of stored Notary signature\n     * @param attPayload        Raw payload with Attestation data\n     * @param agentRoot         Agent Merkle Root from the Attestation\n     * @param snapGas           Gas data for each chain in the Attestation's snapshot\n     * @return wasAccepted      Whether the Attestation was accepted\n     */\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external returns (bool wasAccepted);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the total amount of Notaries attestations that have been accepted.\n     */\n    function attestationsAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns a Notary-signed attestation with a given index.\n     * \u003e Index refers to the list of all attestations accepted by this contract.\n     * @dev Attestations are created on Synapse Chain whenever a Notary-signed snapshot is accepted by Summit.\n     * Will return an empty signature if this contract is deployed on Synapse Chain.\n     * @param index             Attestation index\n     * @return attPayload       Raw payload with Attestation data\n     * @return attSignature     Notary signature for the reported attestation\n     */\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature);\n\n    /**\n     * @notice Returns the gas data for a given chain from the latest accepted attestation with that chain.\n     * @dev Will return empty values if there is no data for the domain,\n     * or if the notary who provided the data is in dispute.\n     * @param domain            Domain for the chain\n     * @return gasData          Gas data for the chain\n     * @return dataMaturity     Gas data age in seconds\n     */\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity);\n\n    /**\n     * Returns status of Destination contract as far as snapshot/agent roots are concerned\n     * @return snapRootTime     Timestamp when latest snapshot root was accepted\n     * @return agentRootTime    Timestamp when latest agent root was accepted\n     * @return notaryIndex      Index of Notary who signed the latest agent root\n     */\n    function destStatus() external view returns (uint40 snapRootTime, uint40 agentRootTime, uint32 notaryIndex);\n\n    /**\n     * Returns Agent Merkle Root to be passed to LightManager once its optimistic period is over.\n     */\n    function nextAgentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns the nonce of the last attestation submitted by a Notary with a given agent index.\n     * @dev Will return zero if the Notary hasn't submitted any attestations yet.\n     */\n    function lastAttestationNonce(uint32 notaryIndex) external view returns (uint32);\n}\n\n// contracts/interfaces/InterfaceLightManager.sol\n\ninterface InterfaceLightManager {\n    /**\n     * @notice Updates agent status, using a proof against the latest known Agent Merkle Root.\n     * @dev Will revert if the provided proof doesn't match the latest merkle root.\n     * @param agent     Agent address\n     * @param status    Structure specifying agent status: (flag, domain, index)\n     * @param proof     Merkle proof of Active status for the agent\n     */\n    function updateAgentStatus(address agent, AgentStatus memory status, bytes32[] memory proof) external;\n\n    /**\n     * @notice Updates the root of Agent Merkle Tree that the Light Manager is tracking.\n     * Could be only called by a local Destination contract, which is supposed to\n     * verify the attested Agent Merkle Roots.\n     * @param agentRoot_    New Agent Merkle Root\n     */\n    function setAgentRoot(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to set the agent root to resolve the \"stuck\" chain\n     * by proposing the new agent root. The contract owner will be able to resolve the proposed\n     * agent root after a certain period of time.\n     * Note: this function could be called multiple times, each time the timer will be reset.\n     * This could only be called if no fresh data has been submitted by the Notaries to the Inbox,\n     * indicating that the chain is stuck for one of the reasons:\n     * - All active Notaries are in Dispute.\n     * - No active Notaries exist under the current agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - Agent root is empty.\n     * - The chain is not in a stuck state (has recently received a fresh data from the Notaries).\n     * @param agentRoot_    New Agent Merkle Root that is proposed to be set\n     */\n    function proposeAgentRootWhenStuck(bytes32 agentRoot_) external;\n\n    /**\n     * @notice Allows contract owner to cancel the previously proposed agent root.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     */\n    function cancelProposedAgentRoot() external;\n\n    /**\n     * @notice Allows contract owner to resolve the previously proposed agent root.\n     * This will update the agent root, allowing the agents to update their status, effectively\n     * resolving the \"stuck\" chain.\n     * @dev Will revert if any of the following conditions is met:\n     * - Caller is not the contract owner.\n     * - No agent root was proposed.\n     * - Not enough time has passed since the agent root was proposed.\n     */\n    function resolveProposedAgentRoot() external;\n\n    /**\n     * @notice Withdraws locked base message tips from local Origin to the recipient.\n     * @dev Could only be remote-called by BondingManager contract on Synapse Chain.\n     * Note: as an extra security check this function returns its own selector, so that\n     * Destination could verify that a \"remote\" function was called when executing a manager message.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function remoteWithdrawTips(uint32 msgOrigin, uint256 proofMaturity, address recipient, uint256 amount)\n        external\n        returns (bytes4 magicValue);\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest proposed agent root and the timestamp when it was proposed.\n     * @dev Will return zero values if no agent root was proposed, or if the proposed agent root\n     * was already resolved.\n     */\n    function proposedAgentRootData() external view returns (bytes32 agentRoot_, uint256 proposedAt_);\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/security/ReentrancyGuardUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\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/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/memory/Attestation.sol\n\n/// Attestation is a memory view over a formatted attestation payload.\ntype Attestation is uint256;\n\nusing AttestationLib for Attestation global;\n\n/// # Attestation\n/// Attestation structure represents the \"Snapshot Merkle Tree\" created from\n/// every Notary snapshot accepted by the Summit contract. Attestation includes\"\n/// the root of the \"Snapshot Merkle Tree\", as well as additional metadata.\n///\n/// ## Steps for creation of \"Snapshot Merkle Tree\":\n/// 1. The list of hashes is composed for states in the Notary snapshot.\n/// 2. The list is padded with zero values until its length is 2**SNAPSHOT_TREE_HEIGHT.\n/// 3. Values from the list are used as leafs and the merkle tree is constructed.\n///\n/// ## Differences between a State and Attestation\n/// Similar to Origin, every derived Notary's \"Snapshot Merkle Root\" is saved in Summit contract.\n/// The main difference is that Origin contract itself is keeping track of an incremental merkle tree,\n/// by inserting the hash of the sent message and calculating the new \"Origin Merkle Root\".\n/// While Summit relies on Guards and Notaries to provide snapshot data, which is used to calculate the\n/// \"Snapshot Merkle Root\".\n///\n/// - Origin's State is \"state of Origin Merkle Tree after N-th message was sent\".\n/// - Summit's Attestation is \"data for the N-th accepted Notary Snapshot\" + \"agent merkle root at the\n/// time snapshot was submitted\" + \"attestation metadata\".\n///\n/// ## Attestation validity\n/// - Attestation is considered \"valid\" in Summit contract, if it matches the N-th (nonce)\n/// snapshot submitted by Notaries, as well as the historical agent merkle root.\n/// - Attestation is considered \"valid\" in Origin contract, if its underlying Snapshot is \"valid\".\n///\n/// - This means that a snapshot could be \"valid\" in Summit contract and \"invalid\" in Origin, if the underlying\n/// snapshot is invalid (i.e. one of the states in the list is invalid).\n/// - The opposite could also be true. If a perfectly valid snapshot was never submitted to Summit, its attestation\n/// would be valid in Origin, but invalid in Summit (it was never accepted, so the metadata would be incorrect).\n///\n/// - Attestation is considered \"globally valid\", if it is valid in the Summit and all the Origin contracts.\n/// # Memory layout of Attestation fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                                                    |\n/// | ---------- | ----------- | ------- | ----- | -------------------------------------------------------------- |\n/// | [000..032) | snapRoot    | bytes32 | 32    | Root for \"Snapshot Merkle Tree\" created from a Notary snapshot |\n/// | [032..064) | dataHash    | bytes32 | 32    | Agent Root and SnapGasHash combined into a single hash         |\n/// | [064..068) | nonce       | uint32  | 4     | Total amount of all accepted Notary snapshots                  |\n/// | [068..073) | blockNumber | uint40  | 5     | Block when this Notary snapshot was accepted in Summit         |\n/// | [073..078) | timestamp   | uint40  | 5     | Time when this Notary snapshot was accepted in Summit          |\n///\n/// @dev Attestation could be signed by a Notary and submitted to `Destination` in order to use if for proving\n/// messages coming from origin chains that the initial snapshot refers to.\nlibrary AttestationLib {\n    using MemViewLib for bytes;\n\n    // TODO: compress three hashes into one?\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_SNAP_ROOT = 0;\n    uint256 private constant OFFSET_DATA_HASH = 32;\n    uint256 private constant OFFSET_NONCE = 64;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 68;\n    uint256 private constant OFFSET_TIMESTAMP = 73;\n\n    // ════════════════════════════════════════════════ ATTESTATION ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Attestation payload with provided fields.\n     * @param snapRoot_     Snapshot merkle tree's root\n     * @param dataHash_     Agent Root and SnapGasHash combined into a single hash\n     * @param nonce_        Attestation Nonce\n     * @param blockNumber_  Block number when attestation was created in Summit\n     * @param timestamp_    Block timestamp when attestation was created in Summit\n     * @return Formatted attestation\n     */\n    function formatAttestation(\n        bytes32 snapRoot_,\n        bytes32 dataHash_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(snapRoot_, dataHash_, nonce_, blockNumber_, timestamp_);\n    }\n\n    /**\n     * @notice Returns an Attestation view over the given payload.\n     * @dev Will revert if the payload is not an attestation.\n     */\n    function castToAttestation(bytes memory payload) internal pure returns (Attestation) {\n        return castToAttestation(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to an Attestation view.\n     * @dev Will revert if the memory view is not over an attestation.\n     */\n    function castToAttestation(MemView memView) internal pure returns (Attestation) {\n        if (!isAttestation(memView)) revert UnformattedAttestation();\n        return Attestation.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Attestation.\n    function isAttestation(MemView memView) internal pure returns (bool) {\n        return memView.len() == ATTESTATION_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Notary to signal\n    /// that the attestation is valid.\n    function hashValid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of an Attestation, that could be later signed by a Guard to signal\n    /// that the attestation is invalid.\n    function hashInvalid(Attestation att) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(attestationInvalidSalt, keccak(attestation))\n        return att.unwrap().keccakSalted(ATTESTATION_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Attestation att) internal pure returns (MemView) {\n        return MemView.wrap(Attestation.unwrap(att));\n    }\n\n    // ════════════════════════════════════════════ ATTESTATION SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns root of the Snapshot merkle tree created in the Summit contract.\n    function snapRoot(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_SNAP_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(Attestation att) internal pure returns (bytes32) {\n        return att.unwrap().index({index_: OFFSET_DATA_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns hash of the Agent Root and SnapGasHash combined into a single hash.\n    function dataHash(bytes32 agentRoot_, bytes32 snapGasHash_) internal pure returns (bytes32) {\n        return keccak256(bytes.concat(agentRoot_, snapGasHash_));\n    }\n\n    /// @notice Returns nonce of Summit contract at the time, when attestation was created.\n    function nonce(Attestation att) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(att.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when attestation was created in Summit.\n    function blockNumber(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when attestation was created in Summit.\n    /// @dev This is the timestamp according to the Synapse Chain.\n    function timestamp(Attestation att) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(att.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n}\n\n// contracts/libs/memory/Receipt.sol\n\n/// Receipt is a memory view over a formatted \"full receipt\" payload.\ntype Receipt is uint256;\n\nusing ReceiptLib for Receipt global;\n\n/// Receipt structure represents a Notary statement that a certain message has been executed in `ExecutionHub`.\n/// - It is possible to prove the correctness of the tips payload using the message hash, therefore tips are not\n///   included in the receipt.\n/// - Receipt is signed by a Notary and submitted to `Summit` in order to initiate the tips distribution for an\n///   executed message.\n/// - If a message execution fails the first time, the `finalExecutor` field will be set to zero address. In this\n///   case, when the message is finally executed successfully, the `finalExecutor` field will be updated. Both\n///   receipts will be considered valid.\n/// # Memory layout of Receipt fields\n///\n/// | Position   | Field         | Type    | Bytes | Description                                      |\n/// | ---------- | ------------- | ------- | ----- | ------------------------------------------------ |\n/// | [000..004) | origin        | uint32  | 4     | Domain where message originated                  |\n/// | [004..008) | destination   | uint32  | 4     | Domain where message was executed                |\n/// | [008..040) | messageHash   | bytes32 | 32    | Hash of the message                              |\n/// | [040..072) | snapshotRoot  | bytes32 | 32    | Snapshot root used for proving the message       |\n/// | [072..073) | stateIndex    | uint8   | 1     | Index of state used for the snapshot proof       |\n/// | [073..093) | attNotary     | address | 20    | Notary who posted attestation with snapshot root |\n/// | [093..113) | firstExecutor | address | 20    | Executor who performed first valid execution     |\n/// | [113..133) | finalExecutor | address | 20    | Executor who successfully executed the message   |\nlibrary ReceiptLib {\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_ORIGIN = 0;\n    uint256 private constant OFFSET_DESTINATION = 4;\n    uint256 private constant OFFSET_MESSAGE_HASH = 8;\n    uint256 private constant OFFSET_SNAPSHOT_ROOT = 40;\n    uint256 private constant OFFSET_STATE_INDEX = 72;\n    uint256 private constant OFFSET_ATT_NOTARY = 73;\n    uint256 private constant OFFSET_FIRST_EXECUTOR = 93;\n    uint256 private constant OFFSET_FINAL_EXECUTOR = 113;\n\n    // ═════════════════════════════════════════════════ RECEIPT ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Receipt payload with provided fields.\n     * @param origin_           Domain where message originated\n     * @param destination_      Domain where message was executed\n     * @param messageHash_      Hash of the message\n     * @param snapshotRoot_     Snapshot root used for proving the message\n     * @param stateIndex_       Index of state used for the snapshot proof\n     * @param attNotary_        Notary who posted attestation with snapshot root\n     * @param firstExecutor_    Executor who performed first valid execution attempt\n     * @param finalExecutor_    Executor who successfully executed the message\n     * @return Formatted receipt\n     */\n    function formatReceipt(\n        uint32 origin_,\n        uint32 destination_,\n        bytes32 messageHash_,\n        bytes32 snapshotRoot_,\n        uint8 stateIndex_,\n        address attNotary_,\n        address firstExecutor_,\n        address finalExecutor_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            origin_, destination_, messageHash_, snapshotRoot_, stateIndex_, attNotary_, firstExecutor_, finalExecutor_\n        );\n    }\n\n    /**\n     * @notice Returns a Receipt view over the given payload.\n     * @dev Will revert if the payload is not a receipt.\n     */\n    function castToReceipt(bytes memory payload) internal pure returns (Receipt) {\n        return castToReceipt(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Receipt view.\n     * @dev Will revert if the memory view is not over a receipt.\n     */\n    function castToReceipt(MemView memView) internal pure returns (Receipt) {\n        if (!isReceipt(memView)) revert UnformattedReceipt();\n        return Receipt.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted Receipt.\n    function isReceipt(MemView memView) internal pure returns (bool) {\n        // Check payload length\n        return memView.len() == RECEIPT_LENGTH;\n    }\n\n    /// @notice Returns the hash of an Receipt, that could be later signed by a Notary to signal\n    /// that the receipt is valid.\n    function hashValid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_VALID_SALT);\n    }\n\n    /// @notice Returns the hash of a Receipt, that could be later signed by a Guard to signal\n    /// that the receipt is invalid.\n    function hashInvalid(Receipt receipt) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(receiptBodyInvalidSalt, keccak(receipt))\n        return receipt.unwrap().keccakSalted(RECEIPT_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Receipt receipt) internal pure returns (MemView) {\n        return MemView.wrap(Receipt.unwrap(receipt));\n    }\n\n    /// @notice Compares two Receipt structures.\n    function equals(Receipt a, Receipt b) internal pure returns (bool) {\n        // Length of a Receipt payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ RECEIPT SLICING ═════════════════════════════════════════════════\n\n    /// @notice Returns receipt's origin field\n    function origin(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's destination field\n    function destination(Receipt receipt) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(receipt.unwrap().indexUint({index_: OFFSET_DESTINATION, bytes_: 4}));\n    }\n\n    /// @notice Returns receipt's \"message hash\" field\n    function messageHash(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_MESSAGE_HASH, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"snapshot root\" field\n    function snapshotRoot(Receipt receipt) internal pure returns (bytes32) {\n        return receipt.unwrap().index({index_: OFFSET_SNAPSHOT_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns receipt's \"state index\" field\n    function stateIndex(Receipt receipt) internal pure returns (uint8) {\n        // Can be safely casted to uint8, since we index a single byte\n        return uint8(receipt.unwrap().indexUint({index_: OFFSET_STATE_INDEX, bytes_: 1}));\n    }\n\n    /// @notice Returns receipt's \"attestation notary\" field\n    function attNotary(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_ATT_NOTARY});\n    }\n\n    /// @notice Returns receipt's \"first executor\" field\n    function firstExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FIRST_EXECUTOR});\n    }\n\n    /// @notice Returns receipt's \"final executor\" field\n    function finalExecutor(Receipt receipt) internal pure returns (address) {\n        return receipt.unwrap().indexAddress({index_: OFFSET_FINAL_EXECUTOR});\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/libs/memory/Snapshot.sol\n\n/// Snapshot is a memory view over a formatted snapshot payload: a list of states.\ntype Snapshot is uint256;\n\nusing SnapshotLib for Snapshot global;\n\n/// # Snapshot\n/// Snapshot structure represents the state of multiple Origin contracts deployed on multiple chains.\n/// In short, snapshot is a list of \"State\" structs. See State.sol for details about the \"State\" structs.\n///\n/// ## Snapshot usage\n/// - Both Guards and Notaries are supposed to form snapshots and sign `snapshot.hash()` to verify its validity.\n/// - Each Guard should be monitoring a set of Origin contracts chosen as they see fit.\n///   - They are expected to form snapshots with Origin states for this set of chains,\n///   sign and submit them to Summit contract.\n/// - Notaries are expected to monitor the Summit contract for new snapshots submitted by the Guards.\n///   - They should be forming their own snapshots using states from snapshots of any of the Guards.\n///   - The states for the Notary snapshots don't have to come from the same Guard snapshot,\n///   or don't even have to be submitted by the same Guard.\n/// - With their signature, Notary effectively \"notarizes\" the work that some Guards have done in Summit contract.\n///   - Notary signature on a snapshot doesn't only verify the validity of the Origins, but also serves as\n///   a proof of liveliness for Guards monitoring these Origins.\n///\n/// ## Snapshot validity\n/// - Snapshot is considered \"valid\" in Origin, if every state referring to that Origin is valid there.\n/// - Snapshot is considered \"globally valid\", if it is \"valid\" in every Origin contract.\n///\n/// # Snapshot memory layout\n///\n/// | Position   | Field       | Type  | Bytes | Description                  |\n/// | ---------- | ----------- | ----- | ----- | ---------------------------- |\n/// | [000..050) | states[0]   | bytes | 50    | Origin State with index==0   |\n/// | [050..100) | states[1]   | bytes | 50    | Origin State with index==1   |\n/// | ...        | ...         | ...   | 50    | ...                          |\n/// | [AAA..BBB) | states[N-1] | bytes | 50    | Origin State with index==N-1 |\n///\n/// @dev Snapshot could be signed by both Guards and Notaries and submitted to `Summit` in order to produce Attestations\n/// that could be used in ExecutionHub for proving the messages coming from origin chains that the snapshot refers to.\nlibrary SnapshotLib {\n    using MemViewLib for bytes;\n    using StateLib for MemView;\n\n    // ═════════════════════════════════════════════════ SNAPSHOT ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted Snapshot payload using a list of States.\n     * @param states    Arrays of State-typed memory views over Origin states\n     * @return Formatted snapshot\n     */\n    function formatSnapshot(State[] memory states) internal view returns (bytes memory) {\n        if (!_isValidAmount(states.length)) revert IncorrectStatesAmount();\n        // First we unwrap State-typed views into untyped memory views\n        uint256 length = states.length;\n        MemView[] memory views = new MemView[](length);\n        for (uint256 i = 0; i \u003c length; ++i) {\n            views[i] = states[i].unwrap();\n        }\n        // Finally, we join them in a single payload. This avoids doing unnecessary copies in the process.\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a Snapshot view over for the given payload.\n     * @dev Will revert if the payload is not a snapshot payload.\n     */\n    function castToSnapshot(bytes memory payload) internal pure returns (Snapshot) {\n        return castToSnapshot(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Snapshot view.\n     * @dev Will revert if the memory view is not over a snapshot payload.\n     */\n    function castToSnapshot(MemView memView) internal pure returns (Snapshot) {\n        if (!isSnapshot(memView)) revert UnformattedSnapshot();\n        return Snapshot.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Snapshot.\n     */\n    function isSnapshot(MemView memView) internal pure returns (bool) {\n        // Snapshot needs to have exactly N * STATE_LENGTH bytes length\n        // N needs to be in [1 .. SNAPSHOT_MAX_STATES] range\n        uint256 length = memView.len();\n        uint256 statesAmount_ = length / STATE_LENGTH;\n        return statesAmount_ * STATE_LENGTH == length \u0026\u0026 _isValidAmount(statesAmount_);\n    }\n\n    /// @notice Returns the hash of a Snapshot, that could be later signed by an Agent  to signal\n    /// that the snapshot is valid.\n    function hashValid(Snapshot snapshot) internal pure returns (bytes32 hashedSnapshot) {\n        // The final hash to sign is keccak(snapshotSalt, keccak(snapshot))\n        return snapshot.unwrap().keccakSalted(SNAPSHOT_VALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Snapshot snapshot) internal pure returns (MemView) {\n        return MemView.wrap(Snapshot.unwrap(snapshot));\n    }\n\n    // ═════════════════════════════════════════════ SNAPSHOT SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns a state with a given index from the snapshot.\n    function state(Snapshot snapshot, uint256 stateIndex) internal pure returns (State) {\n        MemView memView = snapshot.unwrap();\n        uint256 indexFrom = stateIndex * STATE_LENGTH;\n        if (indexFrom \u003e= memView.len()) revert IndexOutOfRange();\n        return memView.slice({index_: indexFrom, len_: STATE_LENGTH}).castToState();\n    }\n\n    /// @notice Returns the amount of states in the snapshot.\n    function statesAmount(Snapshot snapshot) internal pure returns (uint256) {\n        // Each state occupies exactly `STATE_LENGTH` bytes\n        return snapshot.unwrap().len() / STATE_LENGTH;\n    }\n\n    /// @notice Extracts the list of ChainGas structs from the snapshot.\n    function snapGas(Snapshot snapshot) internal pure returns (ChainGas[] memory snapGas_) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        snapGas_ = new ChainGas[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            State state_ = snapshot.state(i);\n            snapGas_[i] = GasDataLib.encodeChainGas(state_.gasData(), state_.origin());\n        }\n    }\n\n    // ═════════════════════════════════════════ SNAPSHOT ROOT CALCULATION ═════════════════════════════════════════════\n\n    /// @notice Returns the root for the \"Snapshot Merkle Tree\" composed of state leafs from the snapshot.\n    function calculateRoot(Snapshot snapshot) internal pure returns (bytes32) {\n        uint256 statesAmount_ = snapshot.statesAmount();\n        bytes32[] memory hashes = new bytes32[](statesAmount_);\n        for (uint256 i = 0; i \u003c statesAmount_; ++i) {\n            // Each State has two sub-leafs, which are used as the \"leafs\" in \"Snapshot Merkle Tree\"\n            // We save their parent in order to calculate the root for the whole tree later\n            hashes[i] = snapshot.state(i).leaf();\n        }\n        // We are subtracting one here, as we already calculated the hashes\n        // for the tree level above the \"leaf level\".\n        MerkleMath.calculateRoot(hashes, SNAPSHOT_TREE_HEIGHT - 1);\n        // hashes[0] now stores the value for the Merkle Root of the list\n        return hashes[0];\n    }\n\n    /// @notice Reconstructs Snapshot merkle Root from State Merkle Data (root + origin domain)\n    /// and proof of inclusion of State Merkle Data (aka State \"left sub-leaf\") in Snapshot Merkle Tree.\n    /// \u003e Reverts if any of these is true:\n    /// \u003e - State index is out of range.\n    /// \u003e - Snapshot Proof length exceeds Snapshot tree Height.\n    /// @param originRoot    Root of Origin Merkle Tree\n    /// @param domain        Domain of Origin chain\n    /// @param snapProof     Proof of inclusion of State Merkle Data into Snapshot Merkle Tree\n    /// @param stateIndex    Index of Origin State in the Snapshot\n    function proofSnapRoot(bytes32 originRoot, uint32 domain, bytes32[] memory snapProof, uint8 stateIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // Index of \"leftLeaf\" is twice the state position in the snapshot\n        // This is because each state is represented by two leaves in the Snapshot Merkle Tree:\n        // - leftLeaf is a hash of (originRoot, originDomain)\n        // - rightLeaf is a hash of (nonce, blockNumber, timestamp, gasData)\n        uint256 leftLeafIndex = uint256(stateIndex) \u003c\u003c 1;\n        // Check that \"leftLeaf\" index fits into Snapshot Merkle Tree\n        if (leftLeafIndex \u003e= (1 \u003c\u003c SNAPSHOT_TREE_HEIGHT)) revert IndexOutOfRange();\n        bytes32 leftLeaf = StateLib.leftLeaf(originRoot, domain);\n        // Reconstruct snapshot root using proof of inclusion\n        // This will revert if snapshot proof length exceeds Snapshot Tree Height\n        return MerkleMath.proofRoot(leftLeafIndex, leftLeaf, snapProof, SNAPSHOT_TREE_HEIGHT);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if snapshot's states amount is valid.\n    function _isValidAmount(uint256 statesAmount_) internal pure returns (bool) {\n        // Need to have at least one state in a snapshot.\n        // Also need to have no more than `SNAPSHOT_MAX_STATES` states in a snapshot.\n        return statesAmount_ != 0 \u0026\u0026 statesAmount_ \u003c= SNAPSHOT_MAX_STATES;\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/ExecutionHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `ExecutionHub` is a parent contract for `Destination`. It is responsible for the following:\n/// - Executing the messages that are proven against the saved Snapshot Merkle Roots.\n/// - Base messages are forwarded to the specified message recipient, ensuring that the original\n///   execution request is fulfilled correctly.\n/// - Manager messages are forwarded to the local `AgentManager` contract.\n/// - Keeping track of the saved Snapshot Merkle Roots (which are accepted in `Destination`).\n/// - Keeping track of message execution Receipts, as well as verify their validity.\nabstract contract ExecutionHub is AgentSecured, ReentrancyGuardUpgradeable, ExecutionHubEvents, IExecutionHub {\n    using Address for address;\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MessageLib for bytes;\n    using ReceiptLib for bytes;\n    using SafeCall for address;\n    using SafeCast for uint256;\n    using TypeCasts for bytes32;\n\n    /// @notice Struct representing stored data for the snapshot root\n    /// @param notaryIndex  Index of Notary who submitted the statement with the snapshot root\n    /// @param attNonce     Nonce of the attestation for this snapshot root\n    /// @param attBN        Summit block number of the attestation for this snapshot root\n    /// @param attTS        Summit timestamp of the attestation for this snapshot root\n    /// @param index        Index of snapshot root in `_roots`\n    /// @param submittedAt  Timestamp when the statement with the snapshot root was submitted\n    /// @param notaryV      V-value from the Notary signature for the attestation\n    // TODO: tight pack this\n    struct SnapRootData {\n        uint32 notaryIndex;\n        uint32 attNonce;\n        uint40 attBN;\n        uint40 attTS;\n        uint32 index;\n        uint40 submittedAt;\n        uint256 sigIndex;\n    }\n\n    /// @notice Struct representing stored receipt data for the message in Execution Hub.\n    /// @param origin       Domain where message originated\n    /// @param rootIndex    Index of snapshot root used for proving the message\n    /// @param stateIndex   Index of state used for the snapshot proof\n    /// @param executor     Executor who successfully executed the message\n    struct ReceiptData {\n        uint32 origin;\n        uint32 rootIndex;\n        uint8 stateIndex;\n        address executor;\n    }\n    // TODO: include nonce?\n    // 24 bits available for tight packing\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @notice (messageHash =\u003e status)\n    /// @dev Messages coming from different origins will always have a different hash\n    /// as origin domain is encoded into the formatted message.\n    /// Thus we can use hash as a key instead of an (origin, hash) tuple.\n    mapping(bytes32 =\u003e ReceiptData) private _receiptData;\n\n    /// @notice First executor who made a valid attempt of executing a message.\n    /// Note: stored only for messages that had Failed status at some point of time\n    mapping(bytes32 =\u003e address) private _firstExecutor;\n\n    /// @dev All saved snapshot roots\n    bytes32[] internal _roots;\n\n    /// @dev Tracks data for all saved snapshot roots\n    mapping(bytes32 =\u003e SnapRootData) internal _rootData;\n\n    /// @dev gap for upgrade safety\n    uint256[46] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═════════════════════════════════════════════ MESSAGE EXECUTION ═════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function execute(\n        bytes memory msgPayload,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex,\n        uint64 gasLimit\n    ) external nonReentrant {\n        // This will revert if payload is not a formatted message payload\n        Message message = msgPayload.castToMessage();\n        Header header = message.header();\n        bytes32 msgLeaf = message.leaf();\n        // Ensure message was meant for this domain\n        if (header.destination() != localDomain) revert IncorrectDestinationDomain();\n        // Ensure message was not sent from this domain\n        if (header.origin() == localDomain) revert IncorrectOriginDomain();\n        // Check that message has not been executed before\n        ReceiptData memory rcptData = _receiptData[msgLeaf];\n        if (rcptData.executor != address(0)) revert AlreadyExecuted();\n        // Check proofs validity\n        SnapRootData memory rootData = _proveAttestation(header, msgLeaf, originProof, snapProof, stateIndex);\n        // Check if optimistic period has passed\n        uint256 proofMaturity = block.timestamp - rootData.submittedAt;\n        if (proofMaturity \u003c header.optimisticPeriod()) revert MessageOptimisticPeriod();\n        uint256 paddedTips;\n        bool success;\n        // Only Base/Manager message flags exist\n        if (header.flag() == MessageFlag.Base) {\n            // This will revert if message body is not a formatted BaseMessage payload\n            BaseMessage baseMessage = message.body().castToBaseMessage();\n            success = _executeBaseMessage(header, proofMaturity, gasLimit, baseMessage);\n            paddedTips = Tips.unwrap(baseMessage.tips());\n        } else {\n            // gasLimit is ignored when executing manager messages\n            success = _executeManagerMessage(header, proofMaturity, message.body());\n        }\n        if (rcptData.origin == 0) {\n            // This is the first valid attempt to execute the message =\u003e save origin and snapshot proof\n            rcptData.origin = header.origin();\n            rcptData.rootIndex = rootData.index;\n            rcptData.stateIndex = stateIndex;\n            if (success) {\n                // This is the successful attempt to execute the message =\u003e save the executor\n                rcptData.executor = msg.sender;\n            } else {\n                // Save as the \"first executor\", if execution failed\n                _firstExecutor[msgLeaf] = msg.sender;\n            }\n            _receiptData[msgLeaf] = rcptData;\n        } else {\n            if (!success) revert AlreadyFailed();\n            // There has been a failed attempt to execute the message before =\u003e don't touch origin and snapshot root\n            // This is the successful attempt to execute the message =\u003e save the executor\n            rcptData.executor = msg.sender;\n            _receiptData[msgLeaf] = rcptData;\n        }\n        emit Executed(header.origin(), msgLeaf, success);\n        if (!_passReceipt(rootData.notaryIndex, rootData.attNonce, msgLeaf, paddedTips, rcptData)) {\n            // Emit event with the recorded tips so that Notaries could form a receipt to submit to Summit\n            emit TipsRecorded(msgLeaf, paddedTips);\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IExecutionHub\n    function getAttestationNonce(bytes32 snapRoot) external view returns (uint32 attNonce) {\n        return _rootData[snapRoot].attNonce;\n    }\n\n    /// @inheritdoc IExecutionHub\n    function isValidReceipt(bytes memory rcptPayload) external view returns (bool isValid) {\n        // This will revert if payload is not a receipt\n        // This will revert if receipt refers to another domain\n        return _isValidReceipt(rcptPayload.castToReceipt());\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageStatus(bytes32 messageHash) external view returns (MessageStatus status) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        if (rcptData.executor != address(0)) {\n            return MessageStatus.Success;\n        } else if (_firstExecutor[messageHash] != address(0)) {\n            return MessageStatus.Failed;\n        } else {\n            return MessageStatus.None;\n        }\n    }\n\n    /// @inheritdoc IExecutionHub\n    function messageReceipt(bytes32 messageHash) external view returns (bytes memory rcptPayload) {\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Return empty payload if there has been no attempt to execute the message\n        if (rcptData.origin == 0) return \"\";\n        return _messageReceipt(messageHash, rcptData);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Passes message content to recipient that conforms to IMessageRecipient interface.\n    function _executeBaseMessage(Header header, uint256 proofMaturity, uint64 gasLimit, BaseMessage baseMessage)\n        internal\n        returns (bool)\n    {\n        // Check that gas limit covers the one requested by the sender.\n        // We let the executor specify gas limit higher than requested to guarantee the execution of\n        // messages with gas limit set too low.\n        Request request = baseMessage.request();\n        if (gasLimit \u003c request.gasLimit()) revert GasLimitTooLow();\n        // TODO: check that the discarded bits are empty\n        address recipient = baseMessage.recipient().bytes32ToAddress();\n        // Forward message content to the recipient, and limit the amount of forwarded gas\n        if (gasleft() \u003c= gasLimit) revert GasSuppliedTooLow();\n        // receiveBaseMessage(origin, nonce, sender, proofMaturity, version, content)\n        bytes memory payload = abi.encodeCall(\n            IMessageRecipient.receiveBaseMessage,\n            (\n                header.origin(),\n                header.nonce(),\n                baseMessage.sender(),\n                proofMaturity,\n                request.version(),\n                baseMessage.content().clone()\n            )\n        );\n        // Pass the base message to the recipient, return the success status of the call\n        return recipient.safeCall({gasLimit: gasLimit, msgValue: 0, payload: payload});\n    }\n\n    /// @dev Uses message body for a call to AgentManager, and checks the returned magic value to ensure that\n    /// only \"remoteX\" functions could be called this way.\n    function _executeManagerMessage(Header header, uint256 proofMaturity, MemView body) internal returns (bool) {\n        // TODO: introduce incentives for executing Manager Messages?\n        CallData callData = body.castToCallData();\n        // Add the (origin, proofMaturity) values to the calldata\n        bytes memory payload = callData.addPrefix(abi.encode(header.origin(), proofMaturity));\n        // functionCall() calls AgentManager and bubbles the revert from the external call\n        bytes memory magicValue = address(agentManager).functionCall(payload);\n        // We check the returned value here to ensure that only \"remoteX\" functions could be called this way.\n        // This is done to prevent an attack by a malicious Notary trying to force Destination to call an arbitrary\n        // function in a local AgentManager. Any other function will not return the required selector,\n        // while the \"remoteX\" functions will perform the proofMaturity check that will make impossible to\n        // submit an attestation and execute a malicious Manager Message immediately, preventing this attack vector.\n        if (magicValue.length != 32 || bytes32(magicValue) != callData.callSelector()) revert IncorrectMagicValue();\n        return true;\n    }\n\n    /// @dev Passes the message receipt to the Inbox contract, if it is deployed on Synapse Chain.\n    /// This ensures that the message receipts for the messages executed on Synapse Chain are passed to Summit\n    /// without a Notary having to sign them.\n    function _passReceipt(\n        uint32 attNotaryIndex,\n        uint32 attNonce,\n        bytes32 messageHash,\n        uint256 paddedTips,\n        ReceiptData memory rcptData\n    ) internal returns (bool) {\n        // Do nothing if contract is not deployed on Synapse Chain\n        if (localDomain != synapseDomain) return false;\n        // Do nothing for messages with no tips (TODO: introduce incentives for manager messages?)\n        if (paddedTips == 0) return false;\n        return InterfaceInbox(inbox).passReceipt({\n            attNotaryIndex: attNotaryIndex,\n            attNonce: attNonce,\n            paddedTips: paddedTips,\n            rcptPayload: _messageReceipt(messageHash, rcptData)\n        });\n    }\n\n    /// @dev Saves a snapshot root with the attestation data provided by a Notary.\n    /// It is assumed that the Notary signature has been checked outside of this contract.\n    function _saveAttestation(Attestation att, uint32 notaryIndex, uint256 sigIndex) internal {\n        bytes32 root = att.snapRoot();\n        if (_rootData[root].submittedAt != 0) revert DuplicatedSnapshotRoot();\n        // TODO: consider using more than 32 bits for the root index\n        _rootData[root] = SnapRootData({\n            notaryIndex: notaryIndex,\n            attNonce: att.nonce(),\n            attBN: att.blockNumber(),\n            attTS: att.timestamp(),\n            index: _roots.length.toUint32(),\n            submittedAt: ChainContext.blockTimestamp(),\n            sigIndex: sigIndex\n        });\n        _roots.push(root);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Checks if receipt body matches the saved data for the referenced message.\n    /// Reverts if destination domain doesn't match the local domain.\n    function _isValidReceipt(Receipt rcpt) internal view returns (bool) {\n        // Check if receipt refers to this chain\n        if (rcpt.destination() != localDomain) revert IncorrectDestinationDomain();\n        bytes32 messageHash = rcpt.messageHash();\n        ReceiptData memory rcptData = _receiptData[messageHash];\n        // Check if there has been a single attempt to execute the message\n        if (rcptData.origin == 0) return false;\n        // Check that origin and state index fields match\n        if (rcpt.origin() != rcptData.origin || rcpt.stateIndex() != rcptData.stateIndex) return false;\n        // Check that snapshot root and notary who submitted it match in the Receipt\n        bytes32 snapRoot = rcpt.snapshotRoot();\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        if (snapRoot != _roots[rcptData.rootIndex] || rcpt.attNotary() != attNotary) return false;\n        // Check if message was executed from the first attempt\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) {\n            // Both first and final executors are saved in receipt data\n            return rcpt.firstExecutor() == rcptData.executor \u0026\u0026 rcpt.finalExecutor() == rcptData.executor;\n        } else {\n            // Message was Failed at some point of time, so both receipts are valid:\n            // \"Failed\": finalExecutor is ZERO\n            // \"Success\": finalExecutor matches executor from saved receipt data\n            address finalExecutor = rcpt.finalExecutor();\n            return rcpt.firstExecutor() == firstExecutor\n                \u0026\u0026 (finalExecutor == address(0) || finalExecutor == rcptData.executor);\n        }\n    }\n\n    /**\n     * @notice Attempts to prove the validity of the cross-chain message.\n     * First, the origin Merkle Root is reconstructed using the origin proof.\n     * Then the origin state's \"left leaf\" is reconstructed using the origin domain.\n     * After that the snapshot Merkle Root is reconstructed using the snapshot proof.\n     * The snapshot root needs to have been submitted by an undisputed Notary.\n     * @dev Reverts if any of the checks fail.\n     * @param header        Memory view over the message header\n     * @param msgLeaf       Message Leaf that was inserted in the Origin Merkle Tree\n     * @param originProof   Proof of inclusion of Message Leaf in the Origin Merkle Tree\n     * @param snapProof     Proof of inclusion of Origin State Left Leaf into Snapshot Merkle Tree\n     * @param stateIndex    Index of Origin State in the Snapshot\n     * @return rootData     Data for the derived snapshot root\n     */\n    function _proveAttestation(\n        Header header,\n        bytes32 msgLeaf,\n        bytes32[] calldata originProof,\n        bytes32[] calldata snapProof,\n        uint8 stateIndex\n    ) internal view returns (SnapRootData memory rootData) {\n        // Reconstruct Origin Merkle Root using the origin proof\n        // Message index in the tree is (nonce - 1), as nonce starts from 1\n        // This will revert if origin proof length exceeds Origin Tree height\n        bytes32 originRoot = MerkleMath.proofRoot(header.nonce() - 1, msgLeaf, originProof, ORIGIN_TREE_HEIGHT);\n        // Reconstruct Snapshot Merkle Root using the snapshot proof\n        // This will revert if:\n        //  - State index is out of range.\n        //  - Snapshot Proof length exceeds Snapshot tree Height.\n        bytes32 snapshotRoot = SnapshotLib.proofSnapRoot(originRoot, header.origin(), snapProof, stateIndex);\n        // Fetch the attestation data for the snapshot root\n        rootData = _rootData[snapshotRoot];\n        // Check if snapshot root has been submitted\n        if (rootData.submittedAt == 0) revert IncorrectSnapshotRoot();\n        // Check that Notary who submitted the attestation is not in dispute\n        if (_notaryDisputeExists(rootData.notaryIndex)) revert NotaryInDispute();\n        // Check that Notary who submitted the attestation isn't in post-dispute timeout\n        if (_notaryDisputeTimeout(rootData.notaryIndex)) revert DisputeTimeoutNotOver();\n    }\n\n    /// @dev Formats the message execution receipt payload for the given hash and receipt data.\n    function _messageReceipt(bytes32 messageHash, ReceiptData memory rcptData)\n        internal\n        view\n        returns (bytes memory rcptPayload)\n    {\n        // Determine the first executor who tried to execute the message\n        address firstExecutor = _firstExecutor[messageHash];\n        if (firstExecutor == address(0)) firstExecutor = rcptData.executor;\n        // Determine the snapshot root that was used for proving the message\n        bytes32 snapRoot = _roots[rcptData.rootIndex];\n        (address attNotary,) = _getAgent(_rootData[snapRoot].notaryIndex);\n        // ExecutionHub does not store the tips,\n        // the Notary will have to derive the proof of tips from the message payload.\n        return ReceiptLib.formatReceipt({\n            origin_: rcptData.origin,\n            destination_: localDomain,\n            messageHash_: messageHash,\n            snapshotRoot_: snapRoot,\n            stateIndex_: rcptData.stateIndex,\n            attNotary_: attNotary,\n            firstExecutor_: firstExecutor,\n            finalExecutor_: rcptData.executor\n        });\n    }\n}\n\n// contracts/Destination.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Destination` contract is used for receiving messages from other chains. It relies on\n/// Notary-signed statements to get the truthful states of the remote chains. These states are then\n/// used to verify the validity of the messages sent from the remote chains.\n/// `Destination` is responsible for the following:\n/// - Accepting the Attestations from the local Inbox contract.\n/// - Using these Attestations to execute the messages (see parent `ExecutionHub`).\n/// - Passing the Agent Merkle Roots from the Attestations to the local LightManager contract,\n///   if deployed on a non-Synapse chain.\n/// - Keeping track of the remote domains GasData submitted by Notaries, that could be later consumed\n///   by the local `GasOracle` contract.\ncontract Destination is ExecutionHub, DestinationEvents, InterfaceDestination {\n    using AttestationLib for bytes;\n    using ByteString for bytes;\n\n    // TODO: this could be further optimized in terms of storage\n    struct StoredAttData {\n        bytes32 agentRoot;\n        bytes32 dataHash;\n    }\n\n    struct StoredGasData {\n        GasData gasData;\n        uint32 notaryIndex;\n        uint40 submittedAt;\n    }\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Invariant: this is either current LightManager root,\n    /// or the pending root to be passed to LightManager once its optimistic period is over.\n    bytes32 internal _nextAgentRoot;\n\n    /// @inheritdoc InterfaceDestination\n    DestinationStatus public destStatus;\n\n    /// @inheritdoc InterfaceDestination\n    mapping(uint32 =\u003e uint32) public lastAttestationNonce;\n\n    /// @dev Stored lookup data for all accepted Notary Attestations\n    StoredAttData[] internal _storedAttestations;\n\n    /// @dev Remote domains GasData submitted by Notaries\n    mapping(uint32 =\u003e StoredGasData) internal _storedGasData;\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {} // solhint-disable-line no-empty-blocks\n\n    /// @notice Initializes Destination contract:\n    /// - msg.sender is set as contract owner\n    function initialize(bytes32 agentRoot) external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize ReeentrancyGuard\n        __ReentrancyGuard_init();\n        // Set Agent Merkle Root in Light Manager\n        if (localDomain != synapseDomain) {\n            _nextAgentRoot = agentRoot;\n            InterfaceLightManager(address(agentManager)).setAgentRoot(agentRoot);\n            destStatus.agentRootTime = ChainContext.blockTimestamp();\n        }\n        // No need to do anything on Synapse Chain, as the agent root is set in BondingManager\n    }\n\n    // ═════════════════════════════════════════════ ACCEPT STATEMENTS ═════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function acceptAttestation(\n        uint32 notaryIndex,\n        uint256 sigIndex,\n        bytes memory attPayload,\n        bytes32 agentRoot,\n        ChainGas[] memory snapGas\n    ) external onlyInbox returns (bool wasAccepted) {\n        // Check that we can trust the Notary data: they are not in dispute, and the dispute timeout is over (if any)\n        if (_notaryDisputeExists(notaryIndex)) revert NotaryInDispute();\n        if (_notaryDisputeTimeout(notaryIndex)) revert DisputeTimeoutNotOver();\n        // First, try passing current agent merkle root\n        // This will revert if payload is not an attestation\n        Attestation att = attPayload.castToAttestation();\n        // Check that this Notary hasn't used a more fresh nonce\n        uint32 attNonce = att.nonce();\n        if (attNonce \u003c= lastAttestationNonce[notaryIndex]) revert OutdatedNonce();\n        lastAttestationNonce[notaryIndex] = attNonce;\n        // This will revert if snapshot root has been previously submitted\n        _saveAttestation(att, notaryIndex, sigIndex);\n        _storedAttestations.push(StoredAttData({agentRoot: agentRoot, dataHash: att.dataHash()}));\n        // Save Agent Root if required, and update the Destination's Status\n        bool rootPending = passAgentRoot();\n        destStatus = _saveAgentRoot(rootPending, agentRoot, notaryIndex);\n        _saveGasData(snapGas, notaryIndex);\n        return true;\n    }\n\n    // ═══════════════════════════════════════════ AGENT ROOT QUARANTINE ═══════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    function passAgentRoot() public returns (bool rootPending) {\n        // Agent root is not passed on Synapse Chain, as it could be accessed via BondingManager\n        if (localDomain == synapseDomain) return false;\n        bytes32 oldRoot = IAgentManager(agentManager).agentRoot();\n        bytes32 newRoot = _nextAgentRoot;\n        // Check if agent root differs from the current one in LightManager\n        if (oldRoot == newRoot) return false;\n        DestinationStatus memory status = destStatus;\n        // Invariant: Notary who supplied `newRoot` was registered as active against `oldRoot`\n        // So we just need to check the Dispute status of the Notary\n        if (_notaryDisputeExists(status.notaryIndex)) {\n            // Remove the pending agent merkle root, as its signer is in dispute\n            _nextAgentRoot = oldRoot;\n            return false;\n        }\n        // If Notary recently won a Dispute, we can optimistically assume that their passed root is valid.\n        // However, we need to wait until the Dispute timeout is over, before passing the new root to LightManager.\n        if (_notaryDisputeTimeout(status.notaryIndex)) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // Check if agent root optimistic period is over\n        if (status.agentRootTime + AGENT_ROOT_OPTIMISTIC_PERIOD \u003e block.timestamp) {\n            // We didn't pass anything, but there is a pending root\n            return true;\n        }\n        // `newRoot` signer was not disputed, and the root optimistic period is over.\n        // Finally, pass the Agent Merkle Root to LightManager\n        InterfaceLightManager(address(agentManager)).setAgentRoot(newRoot);\n        return false;\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceDestination\n    // solhint-disable-next-line ordering\n    function attestationsAmount() external view returns (uint256) {\n        return _roots.length;\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getAttestation(uint256 index) external view returns (bytes memory attPayload, bytes memory attSignature) {\n        if (index \u003e= _roots.length) revert IndexOutOfRange();\n        bytes32 snapRoot = _roots[index];\n        SnapRootData memory rootData = _rootData[snapRoot];\n        StoredAttData memory storedAtt = _storedAttestations[index];\n        attPayload = AttestationLib.formatAttestation({\n            snapRoot_: snapRoot,\n            dataHash_: storedAtt.dataHash,\n            nonce_: rootData.attNonce,\n            blockNumber_: rootData.attBN,\n            timestamp_: rootData.attTS\n        });\n        // Attestation signatures are not required on Synapse Chain, as the attestations could be accessed via Summit.\n        if (localDomain != synapseDomain) {\n            attSignature = IStatementInbox(inbox).getStoredSignature(rootData.sigIndex);\n        }\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function getGasData(uint32 domain) external view returns (GasData gasData, uint256 dataMaturity) {\n        StoredGasData memory storedGasData = _storedGasData[domain];\n        // Form the data to return only if it exists and we can trust it:\n        // - There is stored gas data for the domain\n        // - Notary who provided the data is not in dispute\n        // - Notary who provided the data is not in post-dispute timeout period\n        // forgefmt: disable-next-item\n        if (\n            storedGasData.submittedAt != 0 \u0026\u0026\n            !_notaryDisputeExists(storedGasData.notaryIndex) \u0026\u0026\n            !_notaryDisputeTimeout(storedGasData.notaryIndex)\n        ) {\n            gasData = storedGasData.gasData;\n            dataMaturity = block.timestamp - storedGasData.submittedAt;\n        }\n        // Return empty values if there is no data for the domain, or the notary who provided the data can't be trusted.\n    }\n\n    /// @inheritdoc InterfaceDestination\n    function nextAgentRoot() external view returns (bytes32) {\n        // Return current agent root on Synapse Chain for consistency\n        return localDomain == synapseDomain ? IAgentManager(agentManager).agentRoot() : _nextAgentRoot;\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Saves Agent Merkle Root from the accepted attestation, if there is\n    /// no pending root to be passed to LightManager.\n    /// Returns the updated \"last snapshot root / last agent root\" status struct.\n    function _saveAgentRoot(bool rootPending, bytes32 agentRoot, uint32 notaryIndex)\n        internal\n        returns (DestinationStatus memory status)\n    {\n        status = destStatus;\n        // Update the timestamp for the latest snapshot root\n        status.snapRootTime = ChainContext.blockTimestamp();\n        // No need to save agent roots on Synapse Chain, as they could be accessed via BondingManager\n        // Don't update agent root, if there is already a pending one\n        // Update the data for latest agent root only if it differs from the saved one\n        if (localDomain != synapseDomain \u0026\u0026 !rootPending \u0026\u0026 _nextAgentRoot != agentRoot) {\n            status.agentRootTime = ChainContext.blockTimestamp();\n            status.notaryIndex = notaryIndex;\n            _nextAgentRoot = agentRoot;\n            emit AgentRootAccepted(agentRoot);\n        }\n    }\n\n    /// @dev Saves updated values from the snapshot's gas data list.\n    function _saveGasData(ChainGas[] memory snapGas, uint32 notaryIndex) internal {\n        uint256 statesAmount = snapGas.length;\n        for (uint256 i = 0; i \u003c statesAmount; i++) {\n            ChainGas chainGas = snapGas[i];\n            uint32 domain = chainGas.domain();\n            // Don't save gas data for the local domain\n            if (domain == localDomain) continue;\n            StoredGasData memory storedGasData = _storedGasData[domain];\n            // Check that the gas data is not already saved\n            GasData gasData = chainGas.gasData();\n            if (GasData.unwrap(gasData) == GasData.unwrap(storedGasData.gasData)) continue;\n            // Save the gas data\n            _storedGasData[domain] =\n                StoredGasData({gasData: gasData, notaryIndex: notaryIndex, submittedAt: ChainContext.blockTimestamp()});\n        }\n    }\n}\n\n// test/harnesses/DestinationHarness.t.sol\n\n/// @notice Harness for standalone Go tests.\n/// Do not use for tests requiring interactions between messaging contracts.\ncontract DestinationHarness is Destination {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 domain, address agentManager_, address inbox_) Destination(domain, agentManager_, inbox_) {}\n\n    // TODO: add / remove Agents in standalone Go tests\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/DestinationHarness.t.sol\":\"Versioned\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/DestinationHarness.t.sol\":{\"keccak256\":\"0xfb2c6d956b33cc8a0e2036e54f514531af7f94de34013d9cd8740e3a52f0962f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://884457dab8ecbf3f48d30b5b69c1007e39f8f2b87b6ab14074fa81868ee5a86a\",\"dweb:/ipfs/QmcyXCvka6NtuPEM5rvjj5GiQoezqFdsVkWntVx7PRvaMm\"]}},\"version\":1}"},"hashes":{"version()":"54fd4d50"}}}